Skip to main content
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. A member can hold several reports on the same user, one per report type plus one typeless report. You can send a simple flag (just the userId) or a structured report that says what is being reported and why, withdraw one report or all of them, and read back which reports the current member has filed so your UI can disable the options already used.
Flag and unflag take a userId on TypeScript, iOS, and Android; Flutter takes an AmityUser object. Flag state is read from the loaded user object on every platform.
Per-report-type unflag and the detailed flag-state result ship in the October 2026 SDK releases for TypeScript, iOS, and Android. Flutter keeps the boolean flag state and the all-at-once unflag.

Parameters

Flag a user

Call the flag API when the current user reports another user without saying what or why. The server stores it as a typeless report.

Inputs

Report a profile field or behavior

When you want moderators to know what is being reported and why, use one of two calls on TypeScript, iOS, and Android:
  • Report a profile field with the field and an optional comment. A profile report never carries a reason.
  • Report behavior with a required reason and an optional comment.

Inputs

Profile fields

Your app decides the label to show the member.

Reasons

A behavior report takes a reason from the shared content report-reason list, the same one used when flagging posts, comments, and messages: community guidelines, child endangerment, harassment or bullying, self-harm or suicide, violence or threatening content, selling restricted items, sexual content or nudity, spam or scams, false information, or others. See Flag reasons for each platform’s identifiers. The reason never carries text: for Others, put the reporter’s explanation in comment. Use child endangerment (CHILD_ENDANGERMENT on Android, .childEndangerment on iOS, ChildEndangerment on TypeScript) when a user’s behavior endangers a child, including sharing suspected child sexual abuse material (CSAM).

Rules

  • A member holds one report per report type on a target: one per profile field, one for behavior, and one typeless. Reporting the same type again updates that report; reporting a different type adds a new one.
  • A comment longer than 300 characters after trimming is rejected before any request is sent.
  • Unflagging without a reportType removes all of your reports on that user. Pass a reportType to withdraw just one — see Unflag a user.
  • Any other rule the server enforces returns a validation error (HTTP 422).

Examples

Use the behavior call when the reporter picks a reason, and the profile call when they point at a field. Add a comment to either when the reporter gives extra detail.
To report more than one aspect of the same profile (for example the avatar and the behavior), send a separate call for each. They are stored as distinct reports.
The earlier single call that took reportType, reason, and comment together (flagUser(userId, options) on TypeScript, flagUser(userId, reportType, reason, comment) on Android, and flagUser(withId:reportType:reason:comment:) on iOS) still works but is deprecated. Flagging with only a userId is not deprecated.

Unflag a user

Call the unflag API when the current user withdraws a report from another user. Without a reportType it withdraws every report you filed on that user. With a reportType it withdraws only that one and leaves your other reports in place.

Inputs

Which report is withdrawn

untyped exists only for unflag. It names the typeless report, which the flag API never accepts as a type and which the flag-state result returns as reportType: null.
  • Withdrawing a report you never filed succeeds and changes nothing, so withdrawing twice is safe.
  • Other members’ reports on the same user are never affected, even of the same type.
  • After a per-type unflag you may still hold other reports on that user. Do not set a local “flagged by me” value to false after an unflag; read the flag state again instead.

Check which reports you filed on a user

Use the flag-state API to decide what to show: a “reported” badge, which report options to disable because the current member already used them, and a withdraw action per report. Only the current member’s own reports come back; other members’ reports are never exposed.
The repository call isUserFlaggedByMe is deprecated on TypeScript and iOS. It still works and still returns a boolean, so nothing breaks. Read flag state from the user object instead: isFlaggedByMe for a quick yes/no and getUserFlagsByMe() for the reports. Android never had a repository call; it adds getUserFlagsByMe() next to its existing isFlaggedByMe().

Which one to use

There are two ways to read the flag state. Pick by what the screen is doing. The quick yes/no is a hint built from data the user object already carries:
  • false is exact: you have not reported this user, as of the user object’s last update.
  • true means “maybe”. It can be true for a user you did not report, because of other members’ reports.
  • On TypeScript, iOS and Android, the SDK checks a true with the server in the background, once each time the user’s reports change, and remembers the answer. On TypeScript and iOS an observed user is delivered again with the checked value. On Android the checked value appears the next time the user updates.

Keep the quick yes/no current

A loaded user object is a snapshot: the yes/no is worked out from the user data it was built from, so a user object you already hold does not change after you flag or unflag. Observe the user instead, and read isFlaggedByMe from each update. The observer delivers a new user object after every flag or unflag, so your row or badge stays current without any request.
A report filed on another device shows once the user is refreshed. Call getUserFlagsByMe() when you need the exact state. getUserFlagsByMe() uses the hint of the user object you call it on: when that hint is false (including a false the SDK has already confirmed) it returns no reports without a request. Call it on the user you just observed, or on a freshly loaded one, not on an object you held from before a flag or unflag.

Load the user, then check

getUserFlagsByMe() is called on a user object, so get the user first. Use this when the options to flag or unflag open. A user you already hold from a list, a profile, or a member row works too; it carries the same members.

Migrating from the repository call

The repository call still works but is deprecated on TypeScript and iOS. Replace it with the user object: isFlaggedByMe where you drew a badge from the boolean, and getUserFlagsByMe() where you need the exact answer.

Inputs

Result

Every field is always present; a field the report does not carry is null. The result is read from the server on each call and is not cached. The one exception: when the user’s quick yes/no is false, getUserFlagsByMe() returns no reports without a request.

Withdraw one of the listed reports

Each entry in flags maps to one unflag call. Pass its reportType, or untyped when the entry’s reportType is null.
On Android and iOS the reportType parameter of unflag is optional, and omitting it (or passing nil) withdraws all of your reports. An entry whose reportType is null is the typeless report: pass untyped, not nil.

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 and unflag by userId, and read flag state from the loaded user object (isFlaggedByMe and getUserFlagsByMe()). On TypeScript every user the SDK returns carries both members: a user from getUser, a user list, a member list, or a message preview.
  • Flutter flags and unflags through the loaded AmityUser object, withdraws all reports at once, and exposes a boolean flag state only.
  • The child endangerment reason for behavior reports ships in TypeScript 7.31.0 and in the next Android and iOS releases.
  • The repository call isUserFlaggedByMe is deprecated on TypeScript and iOS and keeps returning a boolean: Promise<boolean> on TypeScript, Bool on iOS. Android has no repository call.
  • isFlaggedByMe is computed from the user data when the user is loaded. false is exact; true can be a false positive, and it only reflects the user as of its last update. TypeScript, iOS and Android check a true with the server in the background. Use it to draw a feed row or a badge, and call getUserFlagsByMe() when you show the options to flag or unflag. getUserFlagsByMe() skips the request when isFlaggedByMe is false.
  • The backend returns the updated user, including its current flagCount, and the SDK saves it. Read flag state after a flag or unflag when your UI needs the updated per-report list.

Get User Information

Retrieve user details and flag status.

Roles and Permissions

Gate moderation actions with permission checks.