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.
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) |
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.
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)
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.