Skip to content
Fluxer API

Admin reports

A report is one complaint filed against a message, an account, or a guild, together with the evidence captured when it was filed. These routes list and search reports, return that evidence, resolve a report with a comment shown to the reporter, hold a report past its retention period, and delete a report before it.

Report submission belongs to the public Reports resource, which defines the report categories and the report reasons a report is filed under.

Reporter contact fields require report:view:reporter_pii on top of report:view. Without it reporter_email, reporter_full_legal_name, and reporter_country_of_residence are null on every report, so a redacted field looks like a field the reporter never supplied.

A report is written once, when the reporter files it. Update report moves it from PENDING to RESOLVED with an optional comment. Schedule user deletion for one of the abuse reasons listed there also resolves the pending reports against the deleted account, with no public comment, and sends each reporter the generic notice Update report describes. A report in the child_safety, underage_user, or self_harm category is never resolved this way and stays PENDING. A report is deleted at the end of its retention period, or earlier through Delete report.

List reports returns this object without message context. Get report returns the Admin report detail object, which extends it.

FieldTypeDescription
report_idsnowflakeThe ID of the report
reporter_id1?snowflakeThe account that filed the report
reporter_tag1 2 18?stringThe reporter username and four-digit discriminator joined by #
reporter_username1 2?stringThe username of the reporter
reporter_global_name1 2?stringThe display name of the reporter, or null when unset
reporter_discriminator1 2?stringThe zero-padded four-digit reporter discriminator
reporter_email3?stringThe email address of the reporter
reporter_full_legal_name3?stringThe legal name supplied with a Digital Services Act notice
reporter_country_of_residence3?stringThe country of residence supplied with a Digital Services Act notice
reported_atISO8601 timestampWhen the report was submitted
statusintegerThe report status
report_typeintegerThe report type
category?stringThe report category, derived from reason when the report has one
reason?7 10?stringThe report reason the report was filed under
reason_label?7 11?stringThe English label of the reason
reason_highest_priority?7 12?booleanWhether the reason is one moderators see first
flow?7 10?report flow answers objectThe answers the reporter gave, described in English
reporter_good_faith_confirmed?7 13?booleanWhether the reporter confirmed the notice in good faith
additional_info?stringThe free-text detail the reporter supplied
reported_user_id14?snowflakeThe reported account, or null for a guild report
reported_user_tag2 18?stringThe reported username and four-digit discriminator joined by #
reported_user_username2?stringThe username of the reported account
reported_user_global_name2?stringThe display name of the reported account, or null when unset
reported_user_discriminator2?stringThe zero-padded four-digit reported account discriminator
reported_user_avatar_hash4?stringThe avatar hash of the reported account, or null when unset
reported_user_bot?2 7 17?booleanWhether the reported account is a bot
reported_webhook_id?7 14?snowflakeThe webhook that sent the reported message
reported_webhook_name?4 7 14?stringThe name the reported message was sent under
reported_webhook_avatar_hash?4 7 14?stringThe avatar hash the reported message was sent with, or null when unset
reported_webhook_default_name?4 7 14 15?stringThe name set on the webhook itself
reported_webhook_default_avatar_hash?4 7 14 15?stringThe avatar hash set on the webhook itself, or null when unset
reported_webhook_type?4 7 14 15?integerThe webhook type
reported_webhook_application_id?4 7 14 15?snowflakeThe application whose bot account created the webhook, or null when a user account created it
reported_webhook_channel_id?4 7 14 15?snowflakeThe channel the webhook belonged to
reported_webhook_guild_id?4 7 14 15?snowflakeThe guild the webhook belonged to
reported_webhook_created_at?7 14?ISO8601 timestampWhen the webhook was created, derived from its ID
reported_webhook_creator_id?4 7 14 15?snowflakeThe account that created the webhook
reported_webhook_creator_tag?4 7 14 15 16 18?stringThe creator username and four-digit discriminator joined by #
reported_webhook_creator_username?4 7 14 15 16?stringThe username of the creator
reported_webhook_creator_global_name?4 7 14 15 16?stringThe display name of the creator, or null when unset
reported_webhook_creator_discriminator?4 7 14 15 16?stringThe zero-padded four-digit creator discriminator
reported_webhook_creator_avatar_hash?4 7 14 15 16?stringThe avatar hash of the creator, or null when unset
reported_guild_id?snowflakeThe reported guild, or null when the report names none
reported_guild_name4?stringThe name of the reported guild
reported_guild_icon_hash4?stringThe icon hash of the reported guild, or null when unset
reported_message_id?snowflakeThe reported message, or null for a user or guild report
reported_channel_id?snowflakeThe channel the reported content was sent in
reported_channel_name4?stringThe channel name, or null for a direct message channel
reported_channel_nsfw5?booleanThe effective NSFW state of the reported channel
reported_guild_invite_code4?stringThe invite code the reported guild was reached by
reported_guild_nsfw_level6?integerThe guild NSFW level
reported_guild_nsfw?4 7?booleanWhether the reported guild was marked NSFW
reported_guild_content_warning_level?4 7?integerThe guild content warning level
reported_guild_content_warning_text?4 7?stringThe guild content warning text (at most 200 characters)
reported_channel_nsfw_override?4 7?booleanThe NSFW override set on the reported channel itself
reported_channel_content_warning_level?4 7?integerThe content warning level set on the channel itself
reported_channel_content_warning_text?4 7?stringThe content warning text set on the channel itself (at most 200 characters)
reported_channel_effective_nsfw?7 8?booleanWhether the channel was NSFW once the guild setting was applied
reported_channel_effective_content_warning_level?7 8?integerThe channel content warning level once the guild setting was applied
reported_channel_effective_content_warning_text?7 8?stringThe channel content warning text once the guild setting was applied
resolved_at9?ISO8601 timestampWhen the report was resolved
resolved_by_admin_id9?snowflakeThe Admin account that resolved the report
public_comment9?stringThe comment shown to the reporter (at most 512 characters)

1 Null for an anonymous Digital Services Act notice, which is filed without a Fluxer account, so every reporter identity field is null exactly when reporter_id is null

2 Resolved from the account when the response is produced, and null when the account can no longer be read

3 Null unless the caller holds report:view:reporter_pii, and null when the reporter supplied no value. For a report filed from an account, reporter_email is the current address of that account, and null when the account no longer exists or has no address. For a Digital Services Act notice it is the verified address the notice was filed with

4 Captured when the report was filed and never updated afterwards

5 The captured effective state when the report recorded one, otherwise the current NSFW state of the reported channel

6 Derived from the captured guild NSFW flag, where true is level 3 and false is level 0. Otherwise it is read from the reported guild, the filing guild, or the channel’s guild

7 Always emitted, so an absent member and a null member mean the same thing

8 Computed when the report was filed by applying the guild setting over the channel setting

9 Null while the report is PENDING and set when it moves to RESOLVED

10 Null on a report filed without a report flow, which includes every report filed before report flows existed

11 Null when reason is null, and the raw reason key when this API does not know the reason

12 Null when reason is null or unknown to this API

13 True on a Digital Services Act notice filed through a report flow, and null on every other report

14 A message a webhook sent has no author account, so its report has a null reported_user_id and null reported user fields, and records the webhook instead. Every webhook field is null on any other report, and a message a bot account sent is reported as that account

15 Read from the webhook when the report was filed, and null when the webhook had already been deleted by then

16 Captured from the account that created the webhook. Null when that account had been deleted by the time the report was filed, while reported_webhook_creator_id still names it. The creator is context for moderators and is not the reported account, so reported_user_id stays null

17 Null when the report names no reported account, which includes a report about a message a webhook sent

18 On an instance with the none tag style the tag of an account that is not a bot is the bare username, with no #0000

For a report in a thread, reported_channel_nsfw, the three reported_channel_effective_ fields, and channel_nsfw of each context entry resolve through the parent channel, as Thread object describes.

{
"report_id": "1502771904419102720",
"reporter_id": "1483920011884392448",
"reporter_tag": "wren#0042",
"reporter_email": null,
"reported_at": "2026-03-04T18:22:10.441Z",
"status": 0,
"report_type": 0,
"category": "harassment",
"reason": "harassment",
"reason_label": "Harassment or bullying",
"reason_highest_priority": false,
"flow": {
"revision_hash": "6b1f0c9e2a7d4413",
"surface": "in_app",
"locale": "de",
"steps": [
{"screen_id": "root_message", "screen_title": "Report message", "option_id": "abuse", "option_label": "Abusive or harmful content", "items": []},
{"screen_id": "abuse", "screen_title": "What does it involve?", "option_id": "harassment", "option_label": "Bullying, harassment or stalking", "items": []},
{"screen_id": "harassment", "screen_title": "How is someone being targeted?", "option_id": "harassment_direct", "option_label": "Repeatedly targeting someone with insults or abuse", "items": []}
]
},
"reporter_good_faith_confirmed": null,
"additional_info": null,
"reported_user_id": "1490118377238528000",
"reported_user_bot": false,
"reported_guild_id": "1471002884199612416",
"reported_message_id": "1502771119476146176",
"reported_channel_id": "1471002884199612420",
"reported_channel_nsfw": false,
"reported_guild_nsfw_level": 0,
"resolved_at": null,
"resolved_by_admin_id": null,
"public_comment": null
}
ValueNameDescription
0PENDINGReport is waiting to be reviewed
1RESOLVEDReport has been reviewed and resolved
ValueNameDescription
0MESSAGEA message was reported
1USERA user was reported
2GUILDA guild was reported

The detail object extends the Admin report object with the evidence too large to return in a list page. Get report emits these members, and List reports omits them.

FieldTypeDescription
mutual_dm_channel_id1?snowflakeThe direct message channel shared by the reporter and the reported account
message_context2array[report message context object]The messages captured around the reported content
message_responses3array[message object]The current state of the same messages, read live
reported_profile_snapshot?4?report profile snapshot objectThe reported profile as it was when the report was filed
legal_hold_until?5?ISO8601 timestampWhen the legal hold on the report ends
legal_hold_reason?5?stringWhy the report is held

1 Set only for a USER report that has both a reporter and a reported account, and null when the two share no direct message channel

2 Empty for a report that captured no message context, which is every user report and every guild report. An entry for which neither the capture nor the report records a channel is left out

3 Resolved when the response is produced, so an edited message differs from its captured entry

4 Always emitted. Null for a report filed before profile snapshots were stored, for a report about a message a webhook sent, and when the stored snapshot cannot be read

5 Always emitted. Null when the report has no hold. Set report legal hold places and clears the hold, and Report retention describes its effect

A context entry preserves a message as it was when the report was filed. Later edits or deletions do not change it, and attachment evidence survives deletion of the original.

A message report captures the reported message together with at most 25 messages before it and at most 25 after it, for at most 51 entries. A Digital Services Act notice about a direct message, a group DM, or a guild channel that @everyone cannot view and read the history of captures the reported message alone. A message whose author account no longer existed at capture time is kept under the DeletedUser identity with discriminator 0000 and its original author ID. A message a webhook sent is captured under the name and avatar it was sent with.

FieldTypeDescription
idsnowflakeThe ID of the message
channel_id1snowflakeThe channel the captured messages were read from
channel_nsfw2?booleanThe current NSFW state of that channel
channel_content_warning_level?3 4?integerThe channel content warning level
channel_content_warning_text?3 4?stringThe channel content warning text
guild_id5?snowflakeThe guild the report is scoped to, or null when the report names none
guild_nsfw_level2?integerThe current guild NSFW level
guild_nsfw?3 4?booleanWhether the guild is marked NSFW
guild_content_warning_level?3 4?integerThe guild content warning level
guild_content_warning_text?3 4?stringThe guild content warning text
contentstringThe captured message content, empty when the message had none
timestamp6ISO8601 timestampWhen the message was sent
attachments7array[report message attachment object]The captured attachment copies
author_id8snowflakeThe author of the message
author_username8stringThe captured author username
author_global_name4?stringThe display name of the author
author_discriminator8stringThe captured zero-padded four-digit author discriminator
author_avatar8?stringThe captured author avatar hash, or null when unset
webhook_id?3 9?snowflakeThe webhook that sent the message
author_bot?3 10?booleanWhether the author account is a bot
missing_attachments?3 11array[report missing attachment object]Attachments that could not be copied into the report

1 The channel of the captured entry, otherwise the reported channel. An entry for which neither records a channel is left out of message_context

2 Read from the current channel or guild, and null when the record can no longer be read

3 Always emitted, so an absent member and a null member mean the same thing

4 Always null, because the capture stores no value for it

5 The reported guild, or the guild the report was filed from, so every entry of one report has the same value

6 Derived from the message ID

7 Fluxer drops an evidence copy that records no file name, resolves to no channel, or receives no download URL, so this array can be shorter than the original

8 For a message a webhook sent, the webhook ID, the name and avatar hash the message was sent with, and the discriminator 0000, as the message object shows the author of a webhook message

9 Null for a message an account sent

10 Read from the author account when the response is produced. Null for a message a webhook sent and for an author account that no longer resolves

11 Empty when every attachment was copied, and on a report filed before missing attachments were recorded. An attachment is listed here when its copy failed or, for a file embedded in the message, when the file was no longer stored

FieldTypeDescription
idsnowflakeThe ID of the attachment
filenamestringThe captured file name
url12stringThe download URL for the evidence copy
nsfw?booleanWhether the attachment was marked NSFW
content_type?stringThe captured MIME type, or null when unknown
width?integerThe pixel width, or null for a non-image attachment
height?integerThe pixel height, or null for a non-image attachment
size?3?integerThe size in bytes, or null when unknown

12 The URL expires after five minutes. Fetch the report again for fresh attachment links

An attachment of a captured message that Fluxer could not copy into the report. It has the captured metadata and no download URL.

FieldTypeDescription
idsnowflakeThe ID of the attachment
filenamestringThe captured file name
nsfw?booleanWhether the attachment was marked NSFW
content_type?stringThe captured MIME type, or null when unknown
width?integerThe pixel width, or null for a non-image attachment
height?integerThe pixel height, or null for a non-image attachment
size13?integerThe size in bytes, or null when unknown

13 0 for a file embedded in the message that was no longer stored when the report was filed

The reported profile as it was when the report was filed. A user report keeps the account, a guild report keeps the guild, and a message report keeps the author account. Each image is a copy Fluxer made when the report was filed, so a later profile change or deletion does not affect it.

FieldTypeDescription
captured_atISO8601 timestampWhen the snapshot was taken
user1?snapshot user objectThe reported account
member2?snapshot member objectThe guild profile of the reported account
guild3?snapshot guild objectThe reported guild

1 Null on a guild report

2 Set when the report names a guild the account was a member of, which is a user report with guild_id or a message report in a guild channel

3 Set on a guild report only

FieldTypeDescription
idsnowflakeThe ID of the account
username4?stringThe username
discriminator4?stringThe zero-padded four-digit discriminator
global_name4?stringThe display name, or null when unset
bio4?stringThe profile bio, or null when unset
pronouns4?stringThe pronouns, or null when unset
avatar4?snapshot asset objectThe avatar, or null when unset
banner4?snapshot asset objectThe profile banner, or null when unset

4 Null for an account whose deletion had started when the report was filed, which is kept by ID alone with no member profile

FieldTypeDescription
guild_idsnowflakeThe guild the profile belongs to
nick?stringThe guild nickname, or null when unset
bio?stringThe guild profile bio, or null when unset
pronouns?stringThe guild profile pronouns, or null when unset
joined_at?ISO8601 timestampWhen the account joined the guild
avatar?snapshot asset objectThe guild avatar, or null when unset
banner?snapshot asset objectThe guild profile banner, or null when unset
FieldTypeDescription
idsnowflakeThe ID of the guild
name?stringThe guild name
vanity_url_code?stringThe vanity invite code, or null when unset
icon?snapshot asset objectThe icon, or null when unset
banner?snapshot asset objectThe banner, or null when unset
splash?snapshot asset objectThe invite splash, or null when unset
FieldTypeDescription
hashstringThe asset hash when the report was filed
url5?stringThe download URL for the copy

5 Expires after five minutes. Null when the image could not be copied into the report, or when no download URL could be made

{
"captured_at": "2026-03-04T18:22:10.502Z",
"user": {
"id": "1490118377238528000",
"username": "marlow",
"discriminator": "0117",
"global_name": "Marlow",
"bio": "Ask me about trains",
"pronouns": null,
"avatar": {"hash": "4be1c7a09d2e3f56", "url": "https://reports.example.com/reports/1502771904419102720/profile/user_avatar/4be1c7a09d2e3f56?X-Amz-Expires=300"},
"banner": null
},
"member": {
"guild_id": "1471002884199612416",
"nick": "Conductor",
"bio": null,
"pronouns": null,
"joined_at": "2026-01-12T09:41:00.000Z",
"avatar": null,
"banner": null
},
"guild": null
}

The answers a reporter gave in a report flow, described in English whatever locale the reporter saw. Fluxer builds the description from the stored IDs when it produces the response, so the labels follow the current catalogue.

FieldTypeDescription
revision_hashstringThe revision hash the reporter’s client sent
surfacestringThe report flow surface, in_app or dsa
locale?stringThe locale the reporter saw the flow in
stepsarray[report flow answer step object]The answered screens in walk order
FieldTypeDescription
screen_idstringThe ID of the screen
screen_title1stringThe English title of the screen
option_id2?stringThe ID of the chosen option
option_label1 2?stringThe English label of the chosen option
items3array[report flow answer item object]The ticked checklist items

1 The raw ID when the current catalogue no longer has the screen or option

2 Null on a checklist screen and an info screen

3 In checklist order, not the order the reporter ticked them, and empty on a choice screen and an info screen

FieldTypeDescription
idstringThe ID of the item
labelstringThe English label of the item, or its raw ID when the current catalogue no longer has it

One entry of the report reason catalogue, as List report reasons returns it.

FieldTypeDescription
keystringThe reason key stored on a report
labelstringThe English label
highest_prioritybooleanWhether moderators see reports with this reason first
legacy_category_messagestringThe category a message report stores
legacy_category_userstringThe category a user report stores
legacy_category_guildstringThe category a guild report stores
{
"key": "csam",
"label": "Child sexual abuse material",
"highest_priority": true,
"legacy_category_message": "child_safety",
"legacy_category_user": "child_safety",
"legacy_category_guild": "child_safety"
}

A report resolution is the reduced view Update report returns. It has the fields the update writes and nothing else.

FieldTypeDescription
report_idsnowflakeThe ID of the report
statusintegerThe report status, always RESOLVED on a successful update
resolved_at?ISO8601 timestampWhen the report was resolved
public_comment?stringThe comment shown to the reporter, or null when none was supplied
{
"report_id": "1502771904419102720",
"status": 1,
"resolved_at": "2026-03-05T11:04:53.902Z",
"public_comment": "Thanks for the report. We actioned the account."
}
FieldTypeDescription
report_idsnowflakeThe ID of the report
legal_hold_until?ISO8601 timestampWhen the hold ends, or null when the report has no hold
legal_hold_reason?stringWhy the report is held, or null when the report has no hold
{
"report_id": "1502771904419102720",
"legal_hold_until": "2027-06-30T00:00:00.000Z",
"legal_hold_reason": "Preservation request from a court"
}

Fluxer deletes a report when its retention period ends, whether it is pending or resolved, together with its stored evidence: the attachment copies, the profile snapshot images, and its search index entry. The reporter’s duplicate-report reservation for it goes too, so the reporter can report the same message, account or guild again.

The retention period is 365 days from when the report was filed, or the number of days in FLUXER_REPORT_RETENTION_DAYS. With FLUXER_RESOLVED_REPORT_RETENTION_DAYS set, a resolved report is deleted that many days after resolved_at when that comes first. A report with a legal hold that ends later is kept until the next run after the hold ends. An evidence copy that a retained report also uses is kept for that report.

The deletion runs once a day in worker. Each run logs one Processed report retention line with the counts it found and deleted and the two periods it used. A report that fails to delete keeps its record and is retried on the next run. Delete report deletes one report straight away by the same rules.

GET/v1/admin/reportsAudit reason

Returns a page of Admin report objects without message context. Requires report:view.

The operation has two branches. Both read the report search index, and both return total, offset, and limit beside the page. A request that supplies status and no other filter takes the status branch, which lists the reports with that status newest first by reported_at and ignores sort_by and sort_order. Every other request takes the search branch, which applies the supplied filters and sort.

The search branch applies no status filter when status is omitted, so a request with no query string returns reports of every status.

An instance with no search backend returns 403 FEATURE_TEMPORARILY_DISABLED on both branches.

FieldTypeDescription
q?1stringFree-text query matched against the searchable report fields (1-1024 characters)
status?pending | resolvedRestrict results to one report status
report_type?message | user | guildRestrict results to one report type
category?stringRestrict results to one submitted category (1-128 characters)
reason?stringRestrict results to one report reason key (1-64 characters)
reporter_id?snowflakeRestrict results to one reporter
reported_user_id?snowflakeRestrict results to one reported account
reported_webhook_id?snowflakeRestrict results to messages one webhook sent
reported_guild_id?snowflakeRestrict results to one reported guild
reported_channel_id?snowflakeRestrict results to one reported channel
guild_context_id?snowflakeRestrict results to reports filed from within one guild
resolved_by_admin_id?snowflakeRestrict results to one resolving Admin account
sort_by?2created_at | reported_at | resolved_atSort field (default reported_at)
sort_order?asc | descSort direction, where asc is oldest first (default desc)
limit?integerMaximum reports to return (1-200, default 50)
offset?3integerReports to skip (0-10000, default 0)

1 Matched against category, additional_info, reported_guild_name, and reported_channel_name only. Omitting it matches every report satisfying the remaining filters

2 created_at orders by the time encoded in the report ID, and reported_at by the submission time stored on the report

3 The next page is requested with a larger offset

FieldTypeDescription
reports1array[Admin report object]Reports in this page, without message context
total2integerIndex hits matching the filters
offsetintegerThe offset this page was read from
limitintegerThe limit this page was read with

1 An index hit whose report record no longer exists is dropped and the request still succeeds, so a full page can hold fewer entries than limit. Fluxer logs the dropped IDs, and a Refresh search index of reports removes them from the index

2 The index count, which still includes hits whose report record no longer exists

StatusBodyCondition
200response bodyReport page was returned
403error responseNo search backend is configured for the instance and the request returns FEATURE_TEMPORARILY_DISABLED

The operation records one Admin audit entry with action search_reports, target type report, and target ID 0 on both branches. The metadata keys are limit, offset, result_count for the reports in this page, and total. The search branch adds sort_by and sort_order. A supplied q adds has_query with the value true, and the query text is not recorded. The supplied filters add status, report_type, category, reason, reported_user_id, reported_webhook_id, reported_guild_id, and reported_channel_id under their own names, reporter_id as reporter_user_id, guild_context_id as context_guild_id, and resolved_by_admin_id as resolved_by_admin_user_id. A 403 records nothing.

200 requests per minute for each authenticated user, on the admin:lookup bucket.

GET/v1/admin/report-reasonsAudit reason

Returns every report reason a report flow can file a report under, with the category each one stores for each report type. Requires report:view.

The labels are English. The list is the catalogue this API was built with, so an admin client can label and filter a reason without a copy of its own.

FieldTypeDescription
reasonsarray[report reason object]Every reason, in catalogue order
StatusBodyCondition
200response bodyThe catalogue was returned

The operation records one Admin audit entry with action list_report_reasons, target type report, target ID 0, and the metadata key result_count.

200 requests per minute for each authenticated user, on the admin:lookup bucket.

GET/v1/admin/reports/{report_id}Audit reason

Returns one Admin report detail object, which adds the captured message context and the live state of those messages. Requires report:view.

The operation answers even when the report search index is unavailable. Reporter contact fields are redacted here exactly as they are in List reports.

FieldTypeDescription
report_idsnowflakeThe ID of the report
StatusBodyCondition
200Admin report detail objectReport was returned
404error responseReport does not exist and the request returns UNKNOWN_REPORT

The operation records one Admin audit entry with action get_report, target type report, the report ID as target ID, and metadata keys report_type and status with the integer values of the report. The attachment download URLs are not recorded. A 404 records nothing.

200 requests per minute for each authenticated user, on the admin:lookup bucket.

PATCH/v1/admin/reports/{report_id}Audit reason

Resolves one report and returns a report resolution object. Requires report:resolve.

status is required and resolved is the only value it accepts, so this route changes no other field.

FieldTypeDescription
report_idsnowflakeThe ID of the report
FieldTypeDescription
statusresolvedThe status to move the report to
public_comment?1stringThe comment shown to the reporter (0-512 characters)
notify_reporter?2booleanWhether the notice to the reporter includes public_comment (default true)
resolution?3stringHow the report was resolved, one of actioned, no_violation, or duplicate

1 Stored as null when it is omitted or empty. Otherwise it is stored, and the resolution notice shows it to the reporter unless notify_reporter is false

2 The reporter is notified either way. False sends the generic notice without the comment, and the comment is still stored on the report

3 Optional, so older admin clients that send none still work. It is not stored on the report, not returned by any report route, and not shown to the reporter. It is recorded in the audit entry

The admin panel always sends resolution. Its resolve form has a required Resolution select with three choices: Action taken (actioned), No violation (no_violation), and Duplicate (duplicate). The browser refuses to submit the form without a choice, and the panel checks again on the server: a submission with no choice, or with any other value, is refused with the error “Choose a resolution” and the report stays pending. After a resolve, the panel confirms the choice in its message, such as “Report resolved: No violation”. The report page itself does not show the choice, because no report route returns it. Staff find it in the resolution metadata of the resolve_report entry in the audit log.

StatusBodyCondition
200report resolution objectReport was resolved
400error responseThe report is already resolved and the request returns REPORT_ALREADY_RESOLVED
404error responseReport does not exist and the request returns UNKNOWN_REPORT

The report moves to RESOLVED and records resolved_at, resolved_by_admin_id, and the public comment.

Fluxer records one Admin audit entry with target type report, target ID equal to the report ID, and action resolve_report. The metadata is report_id, report_type, notify_reporter, reporter_dm_sent, reporter_email_sent, and reporter_dsa_email_sent, plus resolution when the request sets one. When Fluxer does not attempt a notice, reporter_notice_skipped names the reason: reporter_account_deleted, reporter_report_banned, reporter_lookup_failed, or no_reporter_email.

Fluxer notifies the reporter of every resolution. A reporter with an account receives a system direct message, and an email when the account has an address. A Digital Services Act notice has no reporter account, so its verified address receives a decision email with the report ID, the comment when one is shared, and how to appeal. Nothing is sent when the reporter account is deleted or barred from reporting.

A reporter who does not already have the system channel open receives Channel Create, and every session of the reporter receives Message Create. Fluxer logs a delivery failure, and the request still succeeds.

200 requests per minute for each authenticated user, on the admin:lookup bucket.

POST/v1/admin/reports/{report_id}/legal-holdAudit reason

Places or clears a legal hold on one report and returns a report legal hold object. Requires report:resolve.

A held report is kept past the end of its retention period until the hold ends, and Delete report refuses it. A hold can be placed on a pending or a resolved report, and a new hold replaces the previous one.

FieldTypeDescription
report_idsnowflakeThe ID of the report
FieldTypeDescription
legal_hold_until1?ISO8601 timestampWhen the hold ends, or null to clear the hold
legal_hold_reason?2?stringWhy the report is kept (1-512 characters)

1 Must be in the future. A time in the past, or a value that is not an ISO 8601 timestamp, returns 400 INVALID_FORM_BODY on legal_hold_until

2 Required to place a hold, and a missing or null reason returns 400 INVALID_FORM_BODY on legal_hold_reason. Ignored when the hold is cleared, which also clears the reason

StatusBodyCondition
200report legal hold objectThe hold was placed or cleared
400error responseThe end time or the reason is invalid and the request returns INVALID_FORM_BODY
404error responseReport does not exist and the request returns UNKNOWN_REPORT

Fluxer records one Admin audit entry with target type report and the report ID as target ID. Placing a hold records action set_report_legal_hold with the metadata keys report_id, report_type, legal_hold_until, and legal_hold_reason. Clearing a hold records action clear_report_legal_hold with report_id and report_type. Either adds previous_legal_hold_until when the report already had a hold end time stored, including one that has passed. A rejected request records nothing.

200 requests per minute for each authenticated user, on the admin:lookup bucket.

DELETE/v1/admin/reports/{report_id}Audit reason

Deletes one report straight away. Requires report:delete, which report:resolve does not include.

This is the deletion report retention runs, without waiting for the retention period. It removes the report record with its captured message context and profile snapshot, its stored evidence copies, its search index entry, and the reporter’s duplicate-report reservation for it. An evidence copy that another report also uses is kept for that report. A pending or a resolved report can be deleted, and the reporter is not told.

FieldTypeDescription
report_idsnowflakeThe ID of the report
StatusBodyCondition
204emptyThe report was deleted
404error responseReport does not exist and the request returns UNKNOWN_REPORT
409error responseThe report has a legal hold that ends later and the request returns REPORT_UNDER_LEGAL_HOLD

Fluxer records one Admin audit entry with action delete_report, target type report, and the report ID as target ID. The metadata keys are report_id, report_type, status, objects_deleted for the evidence copies removed, and shared_objects_kept for the copies kept because another report uses them. A refused request records nothing.

200 requests per minute for each authenticated user, on the admin:lookup bucket.