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

# Flag and Unflag Users

> Flag users, remove your flag, and check user flag state with social.plus SDK.

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

<Info>
  Flutter exposes flag and unflag actions from an `AmityUser` object.
  TypeScript, iOS, and Android expose repository methods that take a `userId`.
</Info>

<Note>
  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.
</Note>

## Parameters

| Operation         | Required inputs                                        | Platforms                         | Result shape                                                                                               |
| ----------------- | ------------------------------------------------------ | --------------------------------- | ---------------------------------------------------------------------------------------------------------- |
| Flag user         | `userId` (optional: `reportType`, `reason`, `comment`) | TypeScript, iOS, Android          | TypeScript returns `Promise<Amity.User>`; iOS async call throws on failure; Android returns `Completable`. |
| Flag user         | `AmityUser` object                                     | Flutter                           | Returns `Future<AmityUser>`.                                                                               |
| Unflag user       | `userId`                                               | TypeScript, iOS, Android          | TypeScript returns `Promise<boolean>`; iOS async call throws on failure; Android returns `Completable`.    |
| Unflag user       | `AmityUser` object                                     | Flutter                           | Returns `Future<AmityUser>`.                                                                               |
| Check flag status | `userId` or `AmityUser` object                         | TypeScript, iOS, Android, Flutter | Boolean flag state where the platform exposes it.                                                          |

## Flag a user

Call the flag API when the current user reports another user.

### Inputs

| Platform   | Method                                                            | Required inputs                                       | Result shape                                      |
| ---------- | ----------------------------------------------------------------- | ----------------------------------------------------- | ------------------------------------------------- |
| TypeScript | `UserRepository.flagUser(userId, options?)`                       | `userId` (optional `reportType`, `reason`, `comment`) | Returns `Promise<Amity.User>` — 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<AmityUser>`.                      |

<CodeGroup>
  ```typescript TypeScript theme={null}
  import { UserRepository } from '@amityco/ts-sdk';

  async function flagUser(userId: string) {
  const flagged = await UserRepository.flagUser(userId);
  console.log('Flagged:', flagged);
  }

  ```

  ```swift iOS theme={null}
  func flagUser() async {
      do {
          try await userRepository.flagUser(withId: "<user-id>")
          print("User flagged")
      } catch {
          print("Flag failed: \(error)")
      }
  }
  ```

  ```kotlin Android theme={null}
  fun flagUser(userRepository: AmityUserRepository, userId: String) {
      userRepository.flagUser(userId = userId)
          .doOnComplete {
              Log.d("UserFlag", "User flagged")
          }
          .doOnError { error ->
              Log.e("UserFlag", "Flag failed", error)
          }
          .subscribe()
  }
  ```

  ```dart Flutter theme={null}
  Future<void> flagUser(AmityUser user) async {
    try {
      final updatedUser = await user.report().flag();
      print('Flagged user: ${updatedUser.userId}');
    } on AmityException catch (error) {
      print('Flag failed: ${error.message}');
    }
  }
  ```
</CodeGroup>

## 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

<Info>
  * `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.
</Info>

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

<CodeGroup>
  ```typescript TypeScript theme={null}
  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 theme={null}
  // Report a user's behavior, with a reason and comment
  try await userRepository.flagUser(
      withId: "<user-id>",
      reportType: .behavior,
      reason: .spamOrScams,
      comment: "Repeatedly posting promo links"
  )

  // Report a profile field (no reason)
  try await userRepository.flagUser(withId: "<user-id>", reportType: .avatarFileId)
  ```

  ```kotlin Android theme={null}
  // 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()
  ```
</CodeGroup>

<Tip>
  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.
</Tip>

## 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<boolean>`.        |
| 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<AmityUser>`.       |

<CodeGroup>
  ```typescript TypeScript theme={null}
  import { UserRepository } from '@amityco/ts-sdk';

  async function unflagUser(userId: string) {
  const unflagged = await UserRepository.unflagUser(userId);
  console.log('Unflagged:', unflagged);
  }

  ```

  ```swift iOS theme={null}
  func unflagUser() async {
      do {
          try await userRepository.unflagUser(withId: "<user-id>")
          print("User unflagged")
      } catch {
          print("Unflag failed: \(error)")
      }
  }
  ```

  ```kotlin Android theme={null}
  fun unflagUser(userRepository: AmityUserRepository, userId: String) {
      userRepository.unflagUser(userId = userId)
          .doOnComplete {
              Log.d("UserFlag", "User unflagged")
          }
          .doOnError { error ->
              Log.e("UserFlag", "Unflag failed", error)
          }
          .subscribe()
  }
  ```

  ```dart Flutter theme={null}
  Future<void> unflagUser(AmityUser user) async {
    try {
      final updatedUser = await user.report().unflag();
      print('Unflagged user: ${updatedUser.userId}');
    } on AmityException catch (error) {
      print('Unflag failed: ${error.message}');
    }
  }
  ```
</CodeGroup>

## Check whether the current user flagged a user

Use the flag-state API or property to decide whether to show a flag or unflag action.

### Inputs

| Platform   | Method                                      | Required inputs    | Result shape                                  |
| ---------- | ------------------------------------------- | ------------------ | --------------------------------------------- |
| TypeScript | `UserRepository.isUserFlaggedByMe(userId)`  | `userId`           | Returns `Promise<boolean>`.                   |
| 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.    |

<CodeGroup>
  ```typescript TypeScript theme={null}
  import { UserRepository } from '@amityco/ts-sdk';

  async function checkFlagState(userId: string) {
  const isFlagged = await UserRepository.isUserFlaggedByMe(userId);
  console.log('Flagged by me:', isFlagged);
  }

  ```

  ```swift iOS theme={null}
  func checkFlagState() async {
      do {
          let isFlagged = try await userRepository.isUserFlaggedByMe(withId: "<user-id>")
          print("Flagged by me: \(isFlagged)")
      } catch {
          print("Flag-state check failed: \(error)")
      }
  }
  ```

  ```kotlin Android theme={null}
  fun checkFlagState(user: AmityUser) {
      val isFlaggedByMe = user.isFlaggedByMe()
      val totalFlagCount = user.getFlagCount()
      Log.d("UserFlag", "Flagged by me: $isFlaggedByMe, total: $totalFlagCount")
  }
  ```

  ```dart Flutter theme={null}
  void checkFlagState(AmityUser user) {
    final isFlaggedByMe = user.isFlaggedByMe;
    print('Flagged by me: $isFlaggedByMe');
  }
  ```
</CodeGroup>

## Platform notes

* Flagging is a report signal for moderation review; it does not automatically block, ban, or delete the user.
* TypeScript, iOS, and Android flag by `userId`.
* Flutter flags through the loaded `AmityUser` object.
* Android and Flutter expose flag status from the loaded user model.

## Related topics

<CardGroup cols={2}>
  <Card title="Get User Information" href="./get-user-information" icon="user">
    Retrieve user details and flag status.
  </Card>

  <Card title="Roles and Permissions" href="../roles-permissions" icon="shield">
    Gate moderation actions with permission checks.
  </Card>
</CardGroup>
