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

# PII Detection

> Read and redact personally identifiable information metadata on supported SDK text objects.

PII detection metadata is attached to text content when your network has PII detection enabled server-side. The native SDK helpers let apps read detected entities and produce redacted display text without changing the original post, comment, or message.

> [!NOTE]
>
> This page covers the client SDK surface only. Feature enablement, quota, billing, and moderation-console behavior are product or backend concerns and are intentionally not documented here.

## SDK Surface

| Platform | PII metadata helper | Redaction helper | Current SDK note |
| - | - | - | - |
| iOS | `getPIIData()` on `AmityPost`, `AmityComment`, and `AmityMessage` | `redactedText(piiCategories:replaceChar:)` on the same objects | Public helper API is available. |
| Android | `getPIIData()` on `AmityPost`, `AmityComment`, and `AmityMessage` | `redactedText(piiCategories, replaceChar)` on `Data.TEXT` | Public helper API is available for text data. |
| TypeScript | Not exposed in the current public SDK source | Not exposed | Use backend-provided data only if your integration has a separate API contract for it. |
| Flutter | Not exposed in the current public SDK source | Not exposed | Use native SDK helpers through platform code only if your app owns that bridge. |

## Data Model

Each detected entity is represented as a PII item.

| Field | iOS type | Android type | Meaning |
| - | - | - | - |
| `offset` | `Int` | `Int` | Start index of the detected entity in the text. |
| `length` | `Int` | `Int` | Number of characters in the detected entity. |
| `category` | `AmityPIICategory` | `AmityPII.Category` | Normalized category when the SDK has one, or an `others` value for unknown categories. |
| `confidence` | `Double` | `Double` | Detection confidence score from the server-provided metadata. |

## Categories

The current native SDK helpers define dedicated categories for these values.

| Category | iOS | Android |
| - | - | - |
| Email | `.email` | `AmityPII.Category.EMAIL` |
| Phone number | `.phoneNumber` | `AmityPII.Category.PHONE_NUMBER` |
| IP address | `.ipAddress` | `AmityPII.Category.IP_ADDRESS` |
| Address | `.address` | `AmityPII.Category.ADDRESS` |
| Passport number | `.passportNumber` | `AmityPII.Category.PASSPORT_NUMBER` |
| Unknown or newer category | `.others(value)` | `AmityPII.Category.OTHERS(value)` |

> [!TIP]
>
> Handle unknown categories deliberately. The server can introduce category strings before every client UI has a named enum case.

## Parameters

| Parameter | iOS type | Android type | Default | Behavior |
| - | - | - | - | - |
| `piiCategories` | `[AmityPIICategory]` | `List<AmityPII.Category>` | Empty list | Empty means redact every detected category. Provide categories to redact only selected types. |
| `replaceChar` | `Character` | `Char` | `*` | Character used to replace each redacted character. |

## Read and Redact

Use `getPIIData()` when you need entity metadata for moderation UI, highlighting, or audit views. Use `redactedText(...)` when the app should display masked text.

```swift iOS theme={null}
var cancellables = Set<AnyCancellable>()

let livePost = postRepository.getPost(withId: postId)
livePost.$snapshot
    .sink { post in
        guard let post else { return }

        let piiItems = post.getPIIData()
        let redactedText = post.redactedText(
            piiCategories: [.email, .phoneNumber],
            replaceChar: "#"
        )

        piiItems.forEach { pii in
            print("\(pii.category.value): \(pii.offset)-\(pii.length)")
        }

        showSuccessMessage(redactedText)
    }
    .store(in: &cancellables)

let liveComment = commentRepository.getComment(withId: commentId)
liveComment.$snapshot
    .sink { comment in
        guard let comment else { return }
        showSuccessMessage(comment.redactedText())
    }
    .store(in: &cancellables)

let liveMessage = messageRepository.getMessage(messageId)
liveMessage.$snapshot
    .sink { message in
        guard let message else { return }
        showSuccessMessage(message.redactedText())
    }
    .store(in: &cancellables)
```

```kotlin Android theme={null}
import AmityPII

val piiItems = post?.getPIIData().orEmpty()
val redactedText = (post?.getData() as? AmityPost.Data.TEXT)
    ?.redactedText(
        piiCategories = listOf(
            AmityPII.Category.EMAIL,
            AmityPII.Category.PHONE_NUMBER
        ),
        replaceChar = '#'
    )
    .orEmpty()

piiItems.forEach { pii ->
    print("${pii.category}: ${pii.offset}-${pii.length}")
}

val redactedComment = (comment?.getData() as? AmityComment.Data.TEXT)
    ?.redactedText()
    .orEmpty()

val redactedMessage = (message?.getData() as? AmityMessage.Data.TEXT)
    ?.redactedText()
    .orEmpty()

print(redactedText + redactedComment + redactedMessage)
```

## Behavior Notes

* Redaction is non-destructive: it returns a string for display and does not change the stored text.
* The native helpers skip PII ranges that overlap with mention ranges so user and channel mentions are not accidentally masked.
* Metadata can be empty even when content is text. Treat an empty list as "no PII metadata on this object", not as a detection failure.
* Android redaction is available on `Data.TEXT`; non-text post, comment, or message data returns no redacted text through this helper.
* TypeScript and Flutter do not expose public PII helper methods in the current SDK source, so do not document `getPIIData()` or `redactedText()` for those SDKs.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.