diff --git a/social-plus-sdk/core-concepts/user-management/user-operations/flag-unflag-user.mdx b/social-plus-sdk/core-concepts/user-management/user-operations/flag-unflag-user.mdx
index 175af17b..ce519ff7 100644
--- a/social-plus-sdk/core-concepts/user-management/user-operations/flag-unflag-user.mdx
+++ b/social-plus-sdk/core-concepts/user-management/user-operations/flag-unflag-user.mdx
@@ -5,19 +5,29 @@ description: "Flag users, remove your flag, and check user flag state with socia
Use user flagging when a member reports another user for moderator review. Flagging does not block, ban, or delete the user; it records reporting state that moderation workflows can review.
+You can send a simple flag (just the `userId`) or an optional **structured report** that describes _what_ is being reported and _why_ ā see [Add a report type, reason, and comment](#add-a-report-type-reason-and-comment-optional).
+
-Flutter exposes flag and unflag actions from an `AmityUser` object. TypeScript, iOS, and Android expose repository methods that take a `userId`.
+ Flutter exposes flag and unflag actions from an `AmityUser` object.
+ TypeScript, iOS, and Android expose repository methods that take a `userId`.
+
+ The structured report fields (`reportType`, `reason`, `comment`) are
+ **optional** and **backward compatible**. A flag call with no report fields
+ behaves exactly as before. These fields are recorded for moderators and are
+ **not** returned in the API response.
+
+
## Parameters
-| Operation | Required inputs | Platforms | Result shape |
-| --- | --- | --- | --- |
-| Flag user | `userId` | TypeScript, iOS, Android | TypeScript returns `Promise`; iOS async call throws on failure; Android returns `Completable`. |
-| Flag user | `AmityUser` object | Flutter | Returns `Future`. |
-| Unflag user | `userId` | TypeScript, iOS, Android | TypeScript returns `Promise`; iOS async call throws on failure; Android returns `Completable`. |
-| Unflag user | `AmityUser` object | Flutter | Returns `Future`. |
-| Check flag status | `userId` or `AmityUser` object | TypeScript, iOS, Android, Flutter | Boolean flag state where the platform exposes it. |
+| Operation | Required inputs | Platforms | Result shape |
+| ----------------- | ------------------------------------------------------ | --------------------------------- | ---------------------------------------------------------------------------------------------------------- |
+| Flag user | `userId` (optional: `reportType`, `reason`, `comment`) | TypeScript, iOS, Android | TypeScript returns `Promise`; iOS async call throws on failure; Android returns `Completable`. |
+| Flag user | `AmityUser` object | Flutter | Returns `Future`. |
+| Unflag user | `userId` | TypeScript, iOS, Android | TypeScript returns `Promise`; iOS async call throws on failure; Android returns `Completable`. |
+| Unflag user | `AmityUser` object | Flutter | Returns `Future`. |
+| Check flag status | `userId` or `AmityUser` object | TypeScript, iOS, Android, Flutter | Boolean flag state where the platform exposes it. |
## Flag a user
@@ -25,21 +35,22 @@ Call the flag API when the current user reports another user.
### Inputs
-| Platform | Method | Required inputs | Result shape |
-| --- | --- | --- | --- |
-| TypeScript | `UserRepository.flagUser(userId)` | `userId` | Returns `Promise`. |
-| iOS | `userRepository.flagUser(withId:)` | `userId` | Async call that throws on failure. |
-| Android | `userRepository.flagUser(userId)` | `userId` | Returns `Completable`. |
-| Flutter | `user.report().flag()` | `AmityUser` object | Returns `Future`. |
+| Platform | Method | Required inputs | Result shape |
+| ---------- | ----------------------------------------------------------------- | ----------------------------------------------------- | ------------------------------------------------- |
+| TypeScript | `UserRepository.flagUser(userId, options?)` | `userId` (optional `reportType`, `reason`, `comment`) | Returns `Promise` ā the flagged user. |
+| iOS | `userRepository.flagUser(withId:reportType:reason:comment:)` | `userId` (optional `reportType`, `reason`, `comment`) | Async call that throws on failure. |
+| Android | `userRepository.flagUser(userId, reportType?, reason?, comment?)` | `userId` (optional `reportType`, `reason`, `comment`) | Returns `Completable`. |
+| Flutter | `user.report().flag()` | `AmityUser` object | Returns `Future`. |
```typescript TypeScript
import { UserRepository } from '@amityco/ts-sdk';
async function flagUser(userId: string) {
- const flagged = await UserRepository.flagUser(userId);
- console.log('Flagged:', flagged);
+const flagged = await UserRepository.flagUser(userId);
+console.log('Flagged:', flagged);
}
+
```
```swift iOS
@@ -76,29 +87,121 @@ Future flagUser(AmityUser user) async {
}
}
```
+
+
+
+## Add a report type, reason, and comment (optional)
+
+When you want moderators to know _what_ part of a profile is being reported and _why_, attach one or more optional fields to the flag call.
+
+| Field | Answers | Description |
+| ------------ | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
+| `reportType` | **What** | The aspect of the profile being reported. One of `displayName`, `description`, `avatarFileId`, or `behavior`. Omit it for a generic (typeless) report. |
+| `reason` | **Why** | A predefined reason for a `behavior` report. **Required** when `reportType` is `behavior`, and not allowed with any other type. |
+| `comment` | **Detail** | Free-text context from the reporter (max 300 characters). Allowed with any report type, including a typeless report. |
+
+### Report types
+
+`reportType` uses fixed values; your app decides the label to show the member.
+
+| Value | Suggested label | Reports the user's⦠|
+| -------------- | --------------- | ----------------------------- |
+| `displayName` | Username | display name |
+| `description` | Bio | bio / description |
+| `avatarFileId` | Avatar | profile image |
+| `behavior` | Behavior | conduct (requires a `reason`) |
+
+### Reasons
+
+For a `behavior` report, pass a `reason` from the shared content report-reason list (the same values used when flagging posts, comments, and messages): `communityGuidelines`, `harassmentOrBullying`, `selfHarmOrSuicide`, `violenceOrThreateningContent`, `sellingRestrictedItems`, `sexualContentOrNudity`, `spamOrScams`, `falseInformation`, or `others` with a custom string.
+
+### Rules
+
+
+ - `reason` is **required** when `reportType` is `behavior`, and **rejected** for every other type (and for typeless reports).
+ - `reason` and `comment` are each capped at **300 characters**.
+ - A member holds **one report per report type** on a target (up to four typed reports plus one typeless). Reporting the **same** type again updates that report; reporting a **different** type adds a new one.
+ - Unflagging removes **all** of your reports on that user at once ā there is no per-type unflag.
+ - Breaking a rule returns a validation error (HTTP `422`) from the server.
+
+
+### Examples
+
+Pass the optional fields alongside the `userId`. Send `reason` only with a `behavior` report, and add a `comment` on any report type when the reporter provides extra detail.
+
+
+```typescript TypeScript
+import { ContentFlagReasonEnum, UserReportTypeEnum, UserRepository } from '@amityco/ts-sdk';
+
+// Report a user's behavior, with a reason and comment
+await UserRepository.flagUser(userId, {
+ reportType: UserReportTypeEnum.BEHAVIOR,
+ reason: ContentFlagReasonEnum.SpamOrScams,
+ comment: 'Repeatedly posting promo links',
+});
+
+// Report a profile field (no reason)
+await UserRepository.flagUser(userId, { reportType: UserReportTypeEnum.AVATAR });
+```
+
+```swift iOS
+// Report a user's behavior, with a reason and comment
+try await userRepository.flagUser(
+ withId: "",
+ reportType: .behavior,
+ reason: .spamOrScams,
+ comment: "Repeatedly posting promo links"
+)
+
+// Report a profile field (no reason)
+try await userRepository.flagUser(withId: "", reportType: .avatarFileId)
+```
+
+```kotlin Android
+// Report a user's behavior, with a reason and comment
+userRepository.flagUser(
+ userId = userId,
+ reportType = AmityUserReportType.BEHAVIOR,
+ reason = AmityContentFlagReason.SpamOrScams,
+ comment = "Repeatedly posting promo links"
+).subscribe()
+
+// Report a profile field (no reason)
+userRepository.flagUser(
+ userId = userId,
+ reportType = AmityUserReportType.AVATAR
+).subscribe()
+```
+
+ To report more than one aspect of the same profile (for example the avatar
+ **and** the behavior), send a separate flag call for each `reportType`. They
+ are stored as distinct reports.
+
+
## Unflag a user
Call the unflag API when the current user removes their report from another user.
### Inputs
-| Platform | Method | Required inputs | Result shape |
-| --- | --- | --- | --- |
-| TypeScript | `UserRepository.unflagUser(userId)` | `userId` | Returns `Promise`. |
-| iOS | `userRepository.unflagUser(withId:)` | `userId` | Async call that throws on failure. |
-| Android | `userRepository.unflagUser(userId)` | `userId` | Returns `Completable`. |
-| Flutter | `user.report().unflag()` | `AmityUser` object | Returns `Future`. |
+| Platform | Method | Required inputs | Result shape |
+| ---------- | ------------------------------------ | ------------------ | ---------------------------------- |
+| TypeScript | `UserRepository.unflagUser(userId)` | `userId` | Returns `Promise`. |
+| iOS | `userRepository.unflagUser(withId:)` | `userId` | Async call that throws on failure. |
+| Android | `userRepository.unflagUser(userId)` | `userId` | Returns `Completable`. |
+| Flutter | `user.report().unflag()` | `AmityUser` object | Returns `Future`. |
```typescript TypeScript
import { UserRepository } from '@amityco/ts-sdk';
async function unflagUser(userId: string) {
- const unflagged = await UserRepository.unflagUser(userId);
- console.log('Unflagged:', unflagged);
+const unflagged = await UserRepository.unflagUser(userId);
+console.log('Unflagged:', unflagged);
}
+
```
```swift iOS
@@ -135,6 +238,7 @@ Future unflagUser(AmityUser user) async {
}
}
```
+
## Check whether the current user flagged a user
@@ -143,21 +247,22 @@ Use the flag-state API or property to decide whether to show a flag or unflag ac
### Inputs
-| Platform | Method | Required inputs | Result shape |
-| --- | --- | --- | --- |
-| TypeScript | `UserRepository.isUserFlaggedByMe(userId)` | `userId` | Returns `Promise`. |
-| iOS | `userRepository.isUserFlaggedByMe(withId:)` | `userId` | Returns `Bool` from an async call. |
-| Android | `user.isFlaggedByMe()` | `AmityUser` object | Returns `Boolean` from the loaded user model. |
-| Flutter | `user.isFlaggedByMe` | `AmityUser` object | Returns `bool` from the loaded user model. |
+| Platform | Method | Required inputs | Result shape |
+| ---------- | ------------------------------------------- | ------------------ | --------------------------------------------- |
+| TypeScript | `UserRepository.isUserFlaggedByMe(userId)` | `userId` | Returns `Promise`. |
+| iOS | `userRepository.isUserFlaggedByMe(withId:)` | `userId` | Returns `Bool` from an async call. |
+| Android | `user.isFlaggedByMe()` | `AmityUser` object | Returns `Boolean` from the loaded user model. |
+| Flutter | `user.isFlaggedByMe` | `AmityUser` object | Returns `bool` from the loaded user model. |
```typescript TypeScript
import { UserRepository } from '@amityco/ts-sdk';
async function checkFlagState(userId: string) {
- const isFlagged = await UserRepository.isUserFlaggedByMe(userId);
- console.log('Flagged by me:', isFlagged);
+const isFlagged = await UserRepository.isUserFlaggedByMe(userId);
+console.log('Flagged by me:', isFlagged);
}
+
```
```swift iOS
@@ -185,6 +290,7 @@ void checkFlagState(AmityUser user) {
print('Flagged by me: $isFlaggedByMe');
}
```
+
## Platform notes