Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,41 +5,52 @@ 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).

<Info>
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`.
</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` | TypeScript, iOS, Android | TypeScript returns `Promise<boolean>`; 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. |
| 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)` | `userId` | Returns `Promise<boolean>`. |
| 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<AmityUser>`. |
| 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
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
Expand Down Expand Up @@ -76,29 +87,121 @@ Future<void> flagUser(AmityUser user) async {
}
}
```

</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
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: "<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
// 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>`. |
| 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
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
Expand Down Expand Up @@ -135,6 +238,7 @@ Future<void> unflagUser(AmityUser user) async {
}
}
```

</CodeGroup>

## Check whether the current user flagged a user
Expand All @@ -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<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. |
| 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
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
Expand Down Expand Up @@ -185,6 +290,7 @@ void checkFlagState(AmityUser user) {
print('Flagged by me: $isFlaggedByMe');
}
```

</CodeGroup>

## Platform notes
Expand Down
Loading