Skip to content
Fluxer API

Admin users

These routes read and edit any account on the instance. An account has more fields here than the public Users resource returns, including its contact details, its network addresses, and its lifecycle state.

Each mutable field group has its own route, its own ACL, and its own audit action, so there is no combined update.

On an instance where members sign in with a username, Change user email, Verify user email, Resend verification email and Send password reset return 400 EMAIL_UNAVAILABLE_ON_INSTANCE. Create password reset link is the way to reset a password there, and it returns 400 USERNAME_SIGN_IN_ONLY on an email instance.

Every operation on this page records an Admin audit entry, reads included. Get current Admin user is the exception and records nothing. POST /v1/admin/users/{user_id}/avatar-block addresses a user path but belongs to Blocklists.

The complete administrative view of one account. It has every stored flag, the private lifecycle fields, and the contact and network fields that the public user object never exposes.

When the caller lacks user:view:email, user:view:dob, or user:view:ip, Fluxer redacts the fields that the missing ACL protects and still returns every key, so the object shape is identical for every caller.

FieldTypeDescription
idsnowflakeThe ID of the account
usernamestringThe username of the account, unique only together with its discriminator (1-32 characters)
discriminator1integerDiscriminator from 0 to 9999, unpadded
global_name?stringThe display name of the account, or null when unset
botbooleanWhether the account is a bot
systembooleanWhether the account is an official system account
flags2stringAccount flags as an unsigned 64-bit decimal string
premium_flagsintegerPremium flags
avatar?stringThe avatar hash, or null when the account has none
banner?stringThe profile banner hash, or null when the account has none
bio?stringThe profile biography, or null when unset
pronouns?stringThe profile pronouns, or null when unset
accent_color?integerThe profile accent colour packed into an integer, or null when unset
email3?stringThe registered email address, or null when the account has none
email_verified3booleanWhether the registered address has been verified
email_bounced3booleanWhether delivery to the registered address hard bounced
date_of_birth4?stringThe date of birth in YYYY-MM-DD form, or null when none is stored
locale?stringThe saved locale, or null when the account has never set one
premium_type?integerPremium type
premium_since?ISO8601 timestampThe time the premium subscription began, or null when the account has none
premium_until?ISO8601 timestampThe time the premium subscription expires, or null when the account has none
premium_grace_ends_at?ISO8601 timestampThe time the payment grace period ends, or null when no grace period is running
premium_lifetime_sequence?integerThe sequence number of the lifetime purchase, or null when the account holds none
temp_banned_until5?ISO8601 timestampThe time the ban expires, or null when no ban stands
pending_deletion_at?ISO8601 timestampThe time the scheduled deletion runs, or null when none is scheduled
pending_bulk_message_deletion_at6?ISO8601 timestampThe time the account’s own scheduled bulk message deletion runs
deletion_reason_code?integerDeletion reason
deletion_public_reason?stringThe reason shown to the account holder, or null when none was supplied
deletion_audit_log_reason?stringThe private reason stored with the pending deletion, and null without audit_log:view
deletion_scheduled_by?snowflakeThe ID of the account that scheduled the pending deletion, or null when it was not recorded
deletion_scheduled_at?ISO8601 timestampThe time the pending deletion was scheduled, or null when it was not recorded
acls7array[string]Effective Admin ACLs, with at most 106 entries
traits8array[string]The free-form operator labels set on the account, with at most 100 entries
has_totp9booleanWhether a TOTP authenticator is registered
authenticator_types9 12array[integer]Registered authenticator types, with at most 10 entries
last_active_at?ISO8601 timestampThe time of the last recorded activity, or null when none is recorded
last_active_ip10?stringThe IP address the account was last active from
last_active_ip_reverse10 11?stringThe reverse DNS name of that IP address
last_active_location10 11?stringThe approximate location of that IP address

1 An unpadded JSON number here, unlike the zero-padded string discriminator of the Admin user summary and the Admin resolved user embedded in other Admin objects. On an instance with the none tag style every account that is not a bot has 0, and its username is unique on its own

2 Serialised as a decimal string

3 Requires user:view:email. Without it email is null while email_verified and email_bounced are both false regardless of the stored state, so an unverified account and a redacted one are indistinguishable

4 Requires user:view:dob, and without it the field is null

5 Set by Ban user for both ban modes. An expiry that has already passed is reported as null, so an elapsed temporary ban reads the same as no ban

6 Written when the account holder schedules its own bulk message deletion, and cleared by Cancel scheduled message deletion

7 The set written by Set user ACLs, returned in stored order with any value outside the ACL registry left out. This set alone decides whether the account can reach the Admin API, and the STAFF account flag plays no part in that

8 Sorted in ascending order, unlike acls

9 Never redacted, and returned in full to any caller the operation admitted

10 Requires user:view:ip, and without it the field is null and no network lookup is attempted

11 Resolved live from last_active_ip for each response, and null when the lookup fails or returns nothing. The reverse DNS result is cached for one day

12 WEBAUTHN is present only while the account chose passkeys as a second factor. A registered credential does not add it, so has_totp false with an empty array still describes an account holding passkeys

{
"id": "1493004551122763776",
"username": "subject",
"discriminator": 7,
"global_name": null,
"bot": false,
"system": false,
"flags": "8796093022208",
"premium_flags": 0,
"avatar": "a1b2c3d4e5f60718293a4b5c6d7e8f90",
"email": "[email protected]",
"email_verified": true,
"email_bounced": false,
"date_of_birth": "1998-03-21",
"temp_banned_until": null,
"pending_deletion_at": null,
"deletion_reason_code": null,
"acls": [],
"traits": ["early-signup"],
"has_totp": true,
"authenticator_types": [1, 2],
"last_active_at": "2026-08-30T21:04:02.771000+00:00",
"last_active_ip": "203.0.113.24",
"last_active_ip_reverse": "host24.example.com",
"last_active_location": "Stockholm, Sweden"
}

The flags field of the Admin user object is a 64-bit bitfield serialised as an unsigned decimal string. It has every stored flag, including the ones the HTTP API leaves out of its public subset.

ValueNameDescription
1 << 0STAFFAccount is a staff member
1 << 2PARTNERAccount is a partner
1 << 3BUG_HUNTERAccount is a bug hunter
1 << 4FRIENDLY_BOTBot accepts friend requests from users
1 << 5FRIENDLY_BOT_MANUAL_APPROVALBot requires manual approval for friend requests
1 << 6SPAMMERAccount is flagged as a spammer
1 << 7PROFILE_HIDDENProfile details are hidden from other users
1 << 33HIGH_GLOBAL_RATE_LIMITAccount has elevated global rate limits
1 << 34DELETEDAccount has been deleted
1 << 36SELF_DELETEDAccount was self-deleted
1 << 38DISABLEDAccount is disabled
1 << 39HAS_SESSION_STARTEDAccount has started a session
1 << 47RATE_LIMIT_BYPASSAccount can bypass rate limits
1 << 48REPORT_BANNEDAccount is banned from reporting
1 << 49VERIFIED_NOT_UNDERAGEAccount is verified as not underage
1 << 50ACCOUNT_LIMITEDAccount is limited
1 << 51HAS_DISMISSED_PREMIUM_ONBOARDINGAccount has dismissed premium onboarding
1 << 53APP_STORE_REVIEWERAccount belongs to an app store reviewer
1 << 57STAFF_HIDDENStaff status is hidden from public flags
1 << 60AGE_VERIFIED_ADULTAccount has verified its age as an adult through card verification
1 << 62LIMIT_EXEMPTAccount is never limited
ValueNameDescription
1 << 0DISCRIMINATORAccount has a premium discriminator
1 << 1BADGE_HIDDENPremium badge is hidden
1 << 2BADGE_MASKEDPremium badge is masked
1 << 3BADGE_TIMESTAMP_HIDDENPremium badge timestamp is hidden
1 << 4BADGE_SEQUENCE_HIDDENPremium badge sequence is hidden
1 << 5PERKS_SANITIZEDPremium perks are sanitised
1 << 6PURCHASE_DISABLEDPremium purchase is disabled
1 << 7ENABLED_OVERRIDEPremium status has an enabled override
1 << 8PERKS_DISABLEDPremium perks are temporarily disabled
ValueNameDescription
0NONENo premium subscription
1SUBSCRIPTIONActive premium subscription
2LIFETIMELifetime premium subscription
ValueNameDescription
1USER_REQUESTED1Account holder requested deletion
2OTHEROther reason
3SPAMSpam
4CHEATING_OR_EXPLOITATIONCheating or exploitation
5COORDINATED_RAIDINGCoordinated raiding
6AUTOMATION_OR_SELFBOTAutomation or selfbot use
7NONCONSENSUAL_SEXUAL_CONTENTNon-consensual sexual content
8SCAM_OR_SOCIAL_ENGINEERINGScam or social engineering
9CHILD_SEXUAL_CONTENTChild sexual content
10PRIVACY_VIOLATION_OR_DOXXINGPrivacy violation or doxxing
11HARASSMENT_OR_BULLYINGHarassment or bullying
12PAYMENT_FRAUDPayment fraud
13CHILD_SAFETY_VIOLATIONChild safety violation
14BILLING_DISPUTE_OR_ABUSEBilling dispute or abuse
15UNSOLICITED_EXPLICIT_CONTENTUnsolicited explicit content
16GRAPHIC_VIOLENCEGraphic violence
17BAN_EVASIONBan evasion
18TOKEN_OR_CREDENTIAL_SCAMToken or credential scam
19INACTIVITYInactivity
20HATE_SPEECH_OR_EXTREMIST_CONTENTHate speech or extremist content
21MALICIOUS_LINKS_OR_MALWAREMalicious links or malware
22IMPERSONATION_OR_FAKE_IDENTITYImpersonation or fake identity

1 The one value that lowers the minimum scheduling delay to 14 days and suppresses the identifier blocklisting and report auto-resolution described under Schedule user deletion

A reason_code request value outside this registry fails body validation with 400 INVALID_FORM_BODY.

The values Clear user profile fields accepts in fields.

ValueDescription
avatarProfile avatar image
bannerProfile banner image
bioProfile biography
pronounsProfile pronouns
global_nameDisplay name
ValueDescription
friendA mutual friendship
incoming_requestA friend request the account has received
outgoing_requestA friend request the account has sent
blockedAn account this account has blocked

Removing a friendship or friend request removes it for both accounts. Removing a block affects only the account that set it.

A password reset link an administrator hands to the account holder.

FieldTypeDescription
url1stringThe web app reset link, the app base URL followed by /reset#token= and the token
expires_atISO8601 timestampWhen the link stops working

1 The token is in the URL fragment, which a browser never sends to a server. It is the same 64-character token reset a password accepts, and it expires one hour after it is issued

One entry for each authentication session of an account. Terminated sessions remain listed with deleted_at set. No operation returns the session token.

FieldTypeDescription
session_id_hashstringThe base64url-encoded hash of the session ID (8-256 characters)
created_atISO8601 timestampThe time the session was created
approx_last_used_atISO8601 timestampThe approximate time the session was last used
client_ip1stringThe IP address the session was created from
client_ip_reverse1 2?stringThe reverse DNS name of that IP address
client_os3?stringThe client operating system derived from the stored user agent
client_platform3?stringThe client platform derived from the stored user agent
client_location1 2?stringThe approximate location of that IP address
deleted_at?ISO8601 timestampThe time the session was terminated, or null while it is still active

1 Requires user:view:ip. Without it client_ip is the literal string [redacted], both derived fields are null, and no network lookup is attempted

2 Resolved live for each response, and null for that entry when its own lookup fails

3 Derived from the stored user agent at read time, so a session recorded without one reports null for both

{
"session_id_hash": "Zm9vYmFyLXNlc3Npb24taGFzaC1leGFtcGxl",
"created_at": "2026-07-02T11:31:09.400000+00:00",
"approx_last_used_at": "2026-08-30T20:58:14.120000+00:00",
"client_ip": "203.0.113.24",
"client_ip_reverse": "host24.example.com",
"client_os": "Windows",
"client_platform": "Desktop",
"client_location": "Stockholm, Sweden",
"deleted_at": null
}

The account summary embedded in the Admin direct message channel object and the Admin relationship object. It is the Admin user summary that audit entries embed, with avatar added.

FieldTypeDescription
idsnowflakeThe ID of the account
usernamestringThe username of the account
discriminator1stringThe four-digit discriminator of the account
global_name?stringThe display name of the account, or null when unset
avatar?stringThe avatar hash, or null when the account has none

1 Left-padded with zeroes to four digits, unlike the unpadded integer discriminator of the Admin user object

{
"id": "1493004551122763776",
"username": "kelsier",
"discriminator": "0042",
"global_name": "Kelsier",
"avatar": "a1b2c3d4e5f60718293a4b5c6d7e8f90"
}

One entry for each direct message or group direct message channel the account has taken part in. The field names differ from the public channel object.

FieldTypeDescription
channel_idsnowflakeThe ID of the channel
channel_type?integerChannel type, or null when the channel record is unavailable
channel_nsfw?booleanWhether the channel is age-restricted, or null when the channel record is unavailable
guild_nsfw_level1?integerNSFW level of the owning guild
recipient_idsarray[snowflake]The IDs of the channel recipients, with at most 100 entries
recipients2array[Admin resolved user object]The resolved recipient accounts, with at most 100 entries
last_message_id?snowflakeThe ID of the latest message, or null when the channel is empty
is_openbooleanWhether the channel is open in the target account’s client
name?stringThe group name, or null when unnamed
icon?stringThe group icon hash, or null when the group has none
owner_id?snowflakeThe ID of the group owner, or null for a one-to-one direct message

1 Always null

2 Contains only the recipients whose accounts still exist, so it can be shorter than recipient_ids

{
"channel_id": "1496118820043030528",
"channel_type": 3,
"channel_nsfw": false,
"guild_nsfw_level": null,
"recipient_ids": ["1493004551122763776", "1489200013322551296"],
"recipients": [],
"last_message_id": "1500992244771848192",
"is_open": true,
"name": "Weekend plans",
"icon": null,
"owner_id": "1493004551122763776"
}
FieldTypeDescription
target_user_idsnowflakeThe ID of the other account
categorystringRelationship category
nickname?stringThe nickname the account assigned to the other party
since?ISO8601 timestampThe time the relationship was established, or null when unrecorded
target1?Admin resolved user objectThe resolved other account

1 Null when the other account no longer exists, while target_user_id remains present

{
"target_user_id": "1489200013322551296",
"category": "friend",
"nickname": null,
"since": "2026-04-18T14:22:51.006000+00:00",
"target": {
"id": "1489200013322551296",
"username": "operator",
"discriminator": "0042",
"global_name": "Operator"
}
}

One recorded change to the account’s email address or its username and discriminator. The account holder’s own changes appear here, and so do Change user username and Change user email.

FieldTypeDescription
event_id1stringThe ID of the change entry as an unsigned 64-bit decimal string
fieldstringThe field that changed, either email or fluxer_tag
old_value2?stringThe value before the change, or null when the field was unset
new_value2?stringThe value after the change, or null when the field was cleared
reason3?stringThe recorded reason for the change, or null when unrecorded
actor_user_id?snowflakeThe ID of the acting Admin, or null for a user-originated change
event_atISO8601 timestampThe time the change was recorded

1 Sent back as page_token to continue the walk. An entry stored without its own event ID reports the account ID here instead

2 An email entry read without user:view:email keeps the entry and replaces both value fields with the literal string [redacted]. An absent value is null

3 An Admin change records the literal value admin_action

{
"event_id": "1500992244771848192",
"field": "email",
"old_value": "[redacted]",
"new_value": "[redacted]",
"reason": "admin_action",
"actor_user_id": "1489200013322551296",
"event_at": "2026-08-14T07:55:31.882000+00:00"
}

One in-app purchase with the store state behind it. It has more fields than the public store purchase object, and still never exposes a purchase token or the account token.

FieldTypeDescription
idsnowflakeThe ID of the store purchase
user_id?snowflakeThe ID of the linked account, or null when unlinked
providerstringEither app_store or google_play
kindstringEither subscription or gift
slotstringStore slot
environmentstringEither production or sandbox
app_idstringBundle ID or package name of the purchasing app
product_idstringStore product ID
base_plan_id?stringGoogle Play base plan ID, or null
latest_transaction_id1?stringLatest store transaction or order ID
ownership_type2?stringStore ownership type, or null
statestringStore purchase state
store_state3?stringRaw state the store reported, or null
entitledbooleanWhether the purchase grants premium now
expires_at?ISO8601 timestampEnd of the paid period
grace_ends_at?ISO8601 timestampEnd of the store grace period
auto_renew?booleanWhether the subscription renews
started_at?ISO8601 timestampThe time the subscription or purchase started
purchased_at?ISO8601 timestampThe time of the latest payment
revoked_at?ISO8601 timestampThe time the store refunded or revoked it
revocation_reason?stringReason recorded for the revocation, or null
supersededbooleanWhether a newer Google Play purchase replaced it
acknowledged4booleanWhether Fluxer acknowledged it with the store
gift_code?stringGift code minted by a gift purchase, or null
bound_at?ISO8601 timestampThe time the purchase was linked to its account
last_event_at?ISO8601 timestampTime of the latest store event applied
synced_at?ISO8601 timestampThe time Fluxer last read it from the store
created_atISO8601 timestampThe time Fluxer first saw the purchase
updated_atISO8601 timestampThe time the record last changed

1 The App Store transaction ID, or the Google Play order ID

2 The App Store value, such as PURCHASED or FAMILY_SHARED. Null for Google Play

3 The App Store subscription status number as a string, or the Google Play state name. Null for an App Store gift that was never revoked

4 Always true for the App Store. For a Google Play gift, true once the purchase was consumed

{
"id": "1501203318237184000",
"user_id": "1489200013322551296",
"provider": "app_store",
"kind": "subscription",
"slot": "monthly",
"environment": "production",
"app_id": "com.fluxer",
"product_id": "com.fluxer.plutonium.monthly",
"base_plan_id": null,
"latest_transaction_id": "2000000712345678",
"ownership_type": "PURCHASED",
"state": "active",
"store_state": "1",
"entitled": true,
"expires_at": "2026-10-29T09:00:00.000Z",
"grace_ends_at": null,
"auto_renew": true,
"started_at": "2026-09-29T09:00:00.000Z",
"purchased_at": "2026-09-29T09:00:00.000Z",
"revoked_at": null,
"revocation_reason": null,
"superseded": false,
"acknowledged": true,
"gift_code": null,
"bound_at": "2026-09-29T09:00:02.000Z",
"last_event_at": "2026-09-29T09:00:00.000Z",
"synced_at": "2026-09-29T09:00:02.000Z",
"created_at": "2026-09-29T09:00:02.000Z",
"updated_at": "2026-09-29T09:00:02.000Z"
}
FieldTypeDescription
channel_idsnowflakeThe ID of the channel the message was sent in
message_idsnowflakeThe ID of the message to shred
{
"channel_id": "1496118820043030528",
"message_id": "1500992244771848192"
}
GET/v1/admin/usersAudit reason

Lists and searches accounts. Requires user:lookup, and user:view:email or user:view:ip for the selectors marked below. The response has an array of Admin user objects and a total.

Fluxer honours exactly one selector, in this precedence order: user_id, resolve, email, last_active_ip, then the indexed q search. A lower-precedence parameter sent alongside a higher-precedence one is ignored, and the request still succeeds. A request with no selector runs the indexed search with an empty query.

FieldTypeDescription
user_id?1array[snowflake]Exact account IDs, with at most 100 values
resolve?2stringOne exact identifier to resolve (1-1024 characters)
email?3stringExact registered email address (1-320 characters)
last_active_ip?4stringExact last active IP address (1-64 characters)
q?5stringFree-text indexed query (1-1024 characters)
limit?6integerMaximum accounts to return (1-200, default 50)
offset?6integerNumber of results to skip (0-100000, default 0)

1 Repeat the parameter to pass more than one value. The response is unordered and has no entry for an ID that matches no account, so a client matches each returned account by its id

2 Resolves at most one account, and a value containing @ requires user:view:email. An unmatched value returns an empty array

3 Matched exactly after trimming, returns at most one account, and requires user:view:email

4 Matched exactly after trimming against the account’s stored last active address, so a subnet or a partial address matches nothing. Requires user:view:ip

5 Served by the user search index. An instance with no search backend configured returns 403 FEATURE_TEMPORARILY_DISABLED

6 Honoured by the last_active_ip and q selectors. The user_id, resolve, and email selectors ignore both

Fluxer chooses the resolve lookup from the shape of the value. A username#discriminator value resolves the tag, a value that is entirely digits resolves the account ID, and a value containing @ resolves the email address. Every other value resolves a Stripe subscription ID.

A q value that is entirely digits also resolves that exact account ID and places it first, even when the search index did not match it, provided offset is zero. That direct hit raises total by one when the index did not already return it.

FieldTypeDescription
usersarray[Admin user object]The accounts in this page
total1integerThe number of accounts the selector matched

1 The user_id and resolve selectors report the length of users, so total never exceeds the returned page for those two

StatusBodyCondition
2001response bodyAccounts were returned
403error responseMISSING_ACL, because the honoured selector requires user:view:email or user:view:ip
403error responseFEATURE_TEMPORARILY_DISABLED, because the indexed search ran on an instance with no search backend

1 A selector that matches nothing returns an empty users array and a total of zero

The operation records one Admin audit entry with action search_users, target type user, and target ID 0. The metadata keys are selector, result_count for the accounts in users, and total. selector is the honoured selector, one of user_id, resolve, email, last_active_ip, or search for the indexed search.

The user_id selector adds user_id_count for the number of IDs supplied, and user_id when exactly one ID was supplied. The last_active_ip and search selectors add limit and offset. The indexed search adds has_query as true when q is not blank. The resolve, email, last_active_ip, and q values are not recorded. A failed request records nothing.

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

GET/v1/admin/users/@me

Returns the account the request authenticated as, wrapped in a user member. Requires admin:authenticate.

Every Admin credential holds admin:authenticate, so every account that can reach the Admin API can read this route. email, date_of_birth, and the IP fields are returned unredacted whatever the acting credential holds. acls reports the ACL set stored on the account. For an Admin API key credential that set can be wider than what the key itself can use.

FieldTypeDescription
userAdmin user objectThe account the request authenticated as
StatusBodyCondition
200response bodyCurrent Admin was returned
403error responseCredential type is refused, or the account does not hold admin:authenticate

The operation records no Admin audit entry.

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

GET/v1/admin/users/{user_id}Audit reason

Returns one account as a single-element array. Requires user:lookup.

FieldTypeDescription
user_idsnowflakeThe ID of the target account
FieldTypeDescription
users1array[Admin user object]The requested account, or an empty array

1 The response is the same envelope List users returns for its user_id selector, without the total member

StatusBodyCondition
2001response bodyThe lookup completed

1 This operation does not answer 404. An ID with no matching account returns 200 with an empty users array, so a client checks the array length

An account with a pending or completed deletion is still returned, with its lifecycle state visible through pending_deletion_at, deletion_reason_code, and deletion_public_reason.

The operation records one Admin audit entry with action get_user, target type user, the path user_id as target ID, and a metadata key found. found is true when users has the account and false when it is empty.

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

PATCH/v1/admin/users/{user_id}/usernameAudit reason

Replaces the username, allocates or claims a discriminator, and returns the resulting account. Requires user:update:username.

A target account may hold a custom discriminator on a self-hosted instance in the everyone premium mode, and on any other instance only when the feature_custom_discriminator limit resolves to a value above zero for that account.

FieldTypeDescription
user_idsnowflakeThe ID of the target account
FieldTypeDescription
username1stringReplacement username (1-32 characters)
discriminator?2stringRequested discriminator of one to four decimal digits

1 Trimmed before validation, restricted to letters, digits, and underscores, and rejected when it lowercases to everyone or here or contains fluxer or system message

2 Honoured only when the target account may hold a custom discriminator. In every other case, including an omitted field, Fluxer allocates a free discriminator for the submitted username. On an instance with the none tag style an account that is not a bot always gets 0, any other value returns the field code DISCRIMINATOR_NOT_SUPPORTED_ON_INSTANCE, and a username another account holds in any letter case returns USERNAME_ALREADY_TAKEN

FieldTypeDescription
userAdmin user objectThe resulting account
StatusBodyCondition
200response bodyUsername was replaced
400error responsePath or body validation fails, or the requested tag is taken and the request returns TAG_ALREADY_TAKEN
404error responseUNKNOWN_USER, because the account does not exist

TAG_ALREADY_TAKEN also covers a submitted username with no free discriminator left, and an allocation lock the operation cannot get within its 10 second wait.

User Update is emitted to the account’s own sessions, and each guild the account is a member of receives Guild Member Update. Fluxer reindexes the member in each indexed guild in the background, so a member search result can briefly report the previous tag.

The change is recorded in the contact change log and is returned by List user change log with reason set to admin_action and actor_user_id set to the acting Admin.

The operation records one Admin audit entry with action change_username, target type user, and metadata keys old_username, new_username, and discriminator.

100 requests per minute for each authenticated user, on the admin:user:modify bucket.

PATCH/v1/admin/users/{user_id}/emailAudit reason

Replaces the account’s email address and returns the resulting account. Requires user:update:email.

The replacement address is stored unverified. Use Verify user email afterwards to mark it verified, or Resend verification email to let the account holder verify it.

FieldTypeDescription
user_idsnowflakeThe ID of the target account
FieldTypeDescription
email1stringReplacement email address (1-254 characters)

1 Normalised and validated as an email address, but the operation itself does no uniqueness check

FieldTypeDescription
userAdmin user objectThe resulting account
StatusBodyCondition
200response bodyEmail address was replaced
400error responseEMAIL_UNAVAILABLE_ON_INSTANCE, because members sign in with a username
404error responseUNKNOWN_USER, because the account does not exist

email_verified is set to false. The stored bounce marker survives the change, so an address replaced on a bounced account remains marked bounced until a verification clears it.

No notice is sent to the previous or the replacement address. User Update is emitted to the account’s own sessions, and no Guild Member Update follows.

The change is recorded in the contact change log and is returned by List user change log, where both values are replaced with [redacted] for a caller without user:view:email.

The operation records one Admin audit entry with action change_email, target type user, and metadata keys old_email and new_email. The audit log is not redacted on read, so both addresses are visible to any holder of audit_log:view.

100 requests per minute for each authenticated user, on the admin:user:modify bucket.

PUT/v1/admin/users/{user_id}/email-verificationAudit reason

Marks the account’s current email address as verified without a confirmation link, and returns the resulting account. Requires user:update:email.

The operation accepts no request body and never clears verification, so the one way to mark an address unverified is to replace it with Change user email.

FieldTypeDescription
user_idsnowflakeThe ID of the target account
FieldTypeDescription
userAdmin user objectThe resulting account
StatusBodyCondition
2001response bodyEmail address was marked verified
400error responseEMAIL_UNAVAILABLE_ON_INSTANCE, because members sign in with a username
404error responseUNKNOWN_USER, because the account does not exist

1 An account that has no stored email address is still accepted, and email_verified is set to true while email stays null

email_verified becomes true and email_bounced becomes false.

User Update is emitted to the account’s own sessions. The operation records one Admin audit entry with action verify_email, target type user, and a metadata key email with the address as it stood before the write, or the literal null when the account had none.

100 requests per minute for each authenticated user, on the admin:user:modify bucket.

POST/v1/admin/users/{user_id}/verification-emailAudit reason

Requests a new verification email for the account. Requires user:update:email. Returns an empty 204 response.

Each address can receive at most three verification emails in fifteen minutes, independently of the Admin rate limit. Further requests return 429 without issuing a token.

FieldTypeDescription
user_idsnowflakeThe ID of the target account
StatusBodyCondition
204emptyThe request was accepted, whether or not an email was sent
4001error responseThe path parameter is not a snowflake, or the account has no email address
403error responseCredential type or ACL evaluation denies the request, or BOT_USER_AUTH_ENDPOINT_ACCESS_DENIED when the target is a bot
404error responseUNKNOWN_USER, because the account does not exist

1 A missing address returns INVALID_FORM_BODY with the validation code USER_DOES_NOT_HAVE_AN_EMAIL_ADDRESS

A single-use verification token is stored against the account ID and its current address, and the link is emailed to that address. The account’s verification state is unchanged until the link is used.

The operation records one Admin audit entry with action resend_verification_email, target type user, and a metadata key email. No Gateway Dispatch is emitted.

100 requests per minute for each authenticated user, on the admin:user:modify bucket.

POST/v1/admin/users/{user_id}/password-resetAudit reason

Creates a password reset token and emails it to the account holder. Requires user:update:email. Returns an empty 204 response.

FieldTypeDescription
user_idsnowflakeThe ID of the target account
StatusBodyCondition
204emptyThe request was accepted, whether or not an email was sent
4001error responseThe path parameter is not a snowflake, or the account has no email address
404error responseUNKNOWN_USER, because the account does not exist

1 A missing address returns INVALID_FORM_BODY with the validation code USER_DOES_NOT_HAVE_AN_EMAIL_ADDRESS

Unlike Resend verification email, this operation has no limit of three emails per address in fifteen minutes, and it accepts a bot account.

A single-use password reset token is stored against the account ID and its current email address, and the token is emailed to that address. The account’s password, sessions, and other credentials are unchanged until the account holder completes the reset.

The operation records one Admin audit entry with action send_password_reset, target type user, and a metadata key email. No Gateway Dispatch is emitted.

100 requests per minute for each authenticated user, on the admin:user:modify bucket.

POST/v1/admin/users/{user_id}/password-reset-linkAudit reason

Creates a password reset token for the account and returns the link that redeems it, with nothing emailed. Requires user:create:password_reset_link and every ACL the target account holds. A target holding an ACL the caller lacks returns 403 MISSING_ACL, and a bot target returns 403 BOT_USER_AUTH_ENDPOINT_ACCESS_DENIED. Returns a password reset link object.

Only an instance where members sign in with a username serves this operation, and an email instance returns 400 USERNAME_SIGN_IN_ONLY. The account holder opens the link in the web app, which calls validate a password reset token and then reset a password.

FieldTypeDescription
user_idsnowflakeThe ID of the target account
StatusBodyCondition
200password reset link objectThe token was stored and its link returned
400error responseThe path parameter is not a snowflake, or the instance signs members in with email
403error responseACL evaluation denies the request, the target holds an ACL the caller lacks, or the target is a bot
404error responseUNKNOWN_USER, because the account does not exist

Every earlier password reset token for the account is deleted, so a link created before this one stops working. The account’s recovery kit is deleted too, so its key stops working. A single-use password reset token is then stored against the account ID with no email address. The account’s password, sessions, and other credentials are unchanged until the account holder completes the reset.

The operation records one Admin audit entry with action create_password_reset_link and target type user. No Gateway Dispatch is emitted.

100 requests per minute for each authenticated user, on the admin:user:modify bucket.

DELETE/v1/admin/users/{user_id}/recovery-kitAudit reason

Deletes the account’s recovery kit, so its recovery key stops working. Requires user:delete:recovery_kit and every ACL the target account holds, and a target holding an ACL the caller lacks returns 403 MISSING_ACL. Returns no body.

Only an instance where members sign in with a username serves this operation, and an email instance returns 400 USERNAME_SIGN_IN_ONLY. The account holder can issue a new kit from their settings.

FieldTypeDescription
user_idsnowflakeThe ID of the target account
StatusBodyCondition
204noneThe kit was deleted, or the account had none
400error responseThe path parameter is not a snowflake, or the instance signs members in with email
403error responseACL evaluation denies the request, or the target holds an ACL the caller lacks
404error responseUNKNOWN_USER, because the account does not exist

The account’s password, sessions, and other credentials are unchanged. The operation records one Admin audit entry with action revoke_recovery_kit and target type user. No Gateway Dispatch is emitted.

100 requests per minute for each authenticated user, on the admin:user:modify bucket.

PATCH/v1/admin/users/{user_id}/date-of-birthAudit reason

Replaces the stored date of birth and returns the resulting account. Requires user:update:dob.

FieldTypeDescription
user_idsnowflakeThe ID of the target account
FieldTypeDescription
date_of_birth1stringReplacement date in YYYY-MM-DD form

1 Exactly ten characters matching YYYY-MM-DD. The field is required, so there is no way to clear a stored date of birth through this operation

FieldTypeDescription
userAdmin user objectThe resulting account
StatusBodyCondition
200response bodyDate of birth was replaced
404error responseUNKNOWN_USER, because the account does not exist

The new date changes what age-restricted content the account may reach. User Update is emitted to the account’s own sessions.

The change is not written to the contact change log. The operation records one Admin audit entry with action change_dob, target type user, and metadata keys old_dob and new_dob, where an absent previous value is the literal null.

100 requests per minute for each authenticated user, on the admin:user:modify bucket.

DELETE/v1/admin/users/{user_id}/profile-fieldsAudit reason

Clears the named profile fields and returns the resulting account. Requires user:update:profile.

Clearing is the only profile change on this resource. No route sets a biography, display name, avatar, or banner to a new value.

FieldTypeDescription
user_idsnowflakeThe ID of the target account
FieldTypeDescription
fields1array[string]Profile fields to clear, with at most 10 entries

1 Required. An empty array is accepted, clears nothing, and still records an audit entry. A value outside the registry fails body validation

FieldTypeDescription
userAdmin user objectThe resulting account
StatusBodyCondition
200response bodyThe named fields were cleared
404error responseUNKNOWN_USER, because the account does not exist

Clearing avatar or banner schedules the previous asset for deletion.

User Update is emitted to the account’s own sessions, and each guild the account is a member of receives Guild Member Update when the operation changes avatar or global_name.

The operation records one Admin audit entry with action clear_fields, target type user, and a metadata key fields with the submitted names joined by commas.

100 requests per minute for each authenticated user, on the admin:user:modify bucket.

PUT/v1/admin/users/{user_id}/bot-statusAudit reason

Marks the account as a bot or as an ordinary account, and returns the resulting account. Requires user:update:bot_status.

FieldTypeDescription
user_idsnowflakeThe ID of the target account
FieldTypeDescription
bot1booleanWhether the account is a bot

1 Required. Setting it to false also clears system in the same write

FieldTypeDescription
userAdmin user objectThe resulting account
StatusBodyCondition
200response bodyBot status was set
4031error responseCredential type or ACL evaluation denies the request. ACCESS_DENIED when the target holds an Admin ACL and bot is true
404error responseUNKNOWN_USER, because the account does not exist

1 A staff account cannot be converted into a bot. Clear its ACL set with Set user ACLs first

User Update is emitted to the account’s own sessions, and each guild the account is a member of receives Guild Member Update when the write changes bot or system.

The operation records one Admin audit entry with action set_bot_status, target type user, and a metadata key bot. Clearing system as a side effect records no second entry.

100 requests per minute for each authenticated user, on the admin:user:modify bucket.

PUT/v1/admin/users/{user_id}/system-statusAudit reason

Marks the account as an official system account or removes that marker, and returns the resulting account. Requires user:update:bot_status, the same ACL as Set user bot status.

FieldTypeDescription
user_idsnowflakeThe ID of the target account
FieldTypeDescription
system1booleanWhether the account is a system account

1 Required. Setting it to true on an account that is not already a bot fails validation

FieldTypeDescription
userAdmin user objectThe resulting account
StatusBodyCondition
200response bodySystem status was set
404error responseUNKNOWN_USER, because the account does not exist

1 The non-bot case is INVALID_FORM_BODY with the validation code USER_MUST_BE_A_BOT_TO_BE_MARKED_AS_A_SYSTEM_USER on the system path

User Update is emitted to the account’s own sessions, and each guild the account is a member of receives Guild Member Update when the write changes system.

The operation records one Admin audit entry with action set_system_status, target type user, and a metadata key system.

100 requests per minute for each authenticated user, on the admin:user:modify bucket.

PUT/v1/admin/users/{user_id}/aclsAudit reason

Replaces the Admin ACL set held by the account and returns the resulting account. Requires acl:set:user.

The submitted array replaces the stored set outright. An empty array removes every ACL, which also removes the account’s Admin API access and leaves every Admin API key the account created unable to satisfy any operation.

FieldTypeDescription
user_idsnowflakeThe ID of the target account
FieldTypeDescription
acls1array[string]Replacement Admin ACLs, with at most 106 values

1 Required. A value outside the ACL registry fails body validation, and a repeated value is collapsed

FieldTypeDescription
userAdmin user objectThe resulting account
StatusBodyCondition
200response bodyThe ACL set was replaced
400error responsePath or body validation fails, including an acls value outside the ACL registry
403error responseCredential type or ACL evaluation denies the request, or ACCESS_DENIED when the path names the acting account
404error responseUNKNOWN_USER, because the account does not exist

The grant bound is evaluated after the account is resolved, so an unknown ID fails first with 404.

The stored ACL set is replaced and appears in the next Admin user object. The account can reach the Admin API exactly when the new set holds admin:authenticate or *. Narrowing the set narrows every existing session and Admin API key of the account without rotating any credential.

User Update is emitted to the account’s own sessions. The operation records one Admin audit entry with action set_acls, target type user, and a metadata key acls with the submitted values joined by commas.

100 requests per minute for each authenticated user, on the admin:user:modify bucket.

PUT/v1/admin/users/{user_id}/traitsAudit reason

Replaces the account’s trait set and returns the resulting account. Requires user:update:traits.

Traits are free-form operator labels that have no ACL meaning and grant no capability.

FieldTypeDescription
user_idsnowflakeThe ID of the target account
FieldTypeDescription
traits1array[string]Replacement trait set, with at most 100 values of 1 to 128 characters

1 Required. An empty array clears the stored set entirely, and a repeated value is collapsed

FieldTypeDescription
userAdmin user objectThe resulting account
StatusBodyCondition
200response bodyThe trait set was replaced
404error responseUNKNOWN_USER, because the account does not exist

The stored trait set is replaced and is returned sorted by the next Admin user object. User Update is emitted to the account’s own sessions.

The operation records one Admin audit entry with action set_traits and target type user. A non-empty request has a metadata key traits with the submitted values joined by commas, and a request that clears the set has no metadata at all.

100 requests per minute for each authenticated user, on the admin:user:modify bucket.

PATCH/v1/admin/users/{user_id}/flagsAudit reason

Adds and removes account flags and returns the resulting account. Requires user:update:flags.

Additions are applied before removals, so a flag named in both arrays ends up cleared. A bit outside the account flag registry is applied unchanged.

FieldTypeDescription
user_idsnowflakeThe ID of the target account
FieldTypeDescription
add_flags?1array[string]Account flag values to add, with at most 64 entries (default empty)
remove_flags?1array[string]Account flag values to remove, with at most 64 entries (default empty)

1 One 64-bit flag value as an unsigned decimal string, such as 64. A value with several bits is applied as a mask

FieldTypeDescription
userAdmin user objectThe resulting account
StatusBodyCondition
200response bodyFlags were updated
404error responseUNKNOWN_USER, because the account does not exist

Bulk jobs applies the same change to up to 1,000 accounts as a queued update_user_flags task.

User Update is emitted to the account’s own sessions. A change to the account’s public flags also sends Guild Member Update to the account’s guilds.

Removing ACCOUNT_LIMITED or adding LIMIT_EXEMPT also lifts any new conversation limit on the account.

The operation records one Admin audit entry with action update_flags, target type user, and the metadata keys add_flags, remove_flags, and new_flags. An empty array is omitted from the metadata map.

100 requests per minute for each authenticated user, on the admin:user:modify bucket.

PATCH/v1/admin/users/{user_id}/premium-flagsAudit reason

Adds and removes premium flags and returns the resulting account. Requires user:update:flags, the same ACL as Update user flags.

Premium flags control badge display, the premium override, the purchase block, and perk sanitisation. They do not grant or revoke a subscription.

FieldTypeDescription
user_idsnowflakeThe ID of the target account
FieldTypeDescription
add_flags?1array[integer]Premium flag values to add, with at most 64 entries (default empty)
remove_flags?1array[integer]Premium flag values to remove, with at most 64 entries (default empty)

1 Each entry is one 32-bit flag value, such as 2. Additions are applied before removals

FieldTypeDescription
userAdmin user objectThe resulting account
StatusBodyCondition
200response bodyPremium flags were updated
404error responseUNKNOWN_USER, because the account does not exist

Premium badge display reflects the new flags. User Update is emitted to the account’s own sessions.

The operation records one Admin audit entry with action update_premium_flags, target type user, and the metadata keys add_flags, remove_flags, and new_flags.

100 requests per minute for each authenticated user, on the admin:user:modify bucket.

GET/v1/admin/users/{user_id}/store-purchasesAudit reason

Lists the in-app purchases linked to an account, newest first. Requires user:lookup. A self-hosted instance never serves this route.

FieldTypeDescription
user_idsnowflakeThe ID of the target account
FieldTypeDescription
purchasesarray[Admin store purchase object]The linked purchases
StatusBodyCondition
200response bodyThe purchases were listed
404error responseUNKNOWN_USER, because the account does not exist

The operation records one Admin audit entry with action list_user_store_purchases, target type user, and the metadata key result_count.

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

POST/v1/admin/users/{user_id}/store-purchases/refreshAudit reason

Reads every purchase linked to an account again from its store, applies the result to the account, and returns the updated purchases. Requires user:update:flags, the same ACL as Update user premium flags. A self-hosted instance never serves this route.

FieldTypeDescription
user_idsnowflakeThe ID of the target account
FieldTypeDescription
purchasesarray[Admin store purchase object]The linked purchases after the refresh
StatusBodyCondition
200response bodyThe purchases were refreshed
404error responseUNKNOWN_USER, because the account does not exist
503error responseSTORE_BILLING_UNAVAILABLE, because a store could not be reached

A subscription the store no longer recognises becomes expired and stops granting premium. A changed premium state sends User Update to the account’s own sessions.

The operation records one Admin audit entry with action refresh_store_purchases, target type user, and the metadata key purchase_count.

100 requests per minute for each authenticated user, on the admin:user:modify bucket.

PUT/v1/admin/users/{user_id}/banAudit reason

Disables an account temporarily or permanently and returns the resulting account. Requires user:temp_ban.

FieldTypeDescription
user_idsnowflakeThe ID of the target account
FieldTypeDescription
duration_hours1integerWhole-hour ban length, where 0 bans permanently (0-8760)
reason?2stringStatement of reasons sent to the banned account holder (at most 512 characters)
notify_user?3booleanWhether to email the account holder about a temporary ban (default true)

1 Required. The expiry is computed from the moment the ban is applied, so no absolute-expiry field is accepted. The 8760 ceiling is one year

2 Included in the temporary ban email and in the audit entry, but not stored on the account, so no read operation returns it

3 A permanent ban sends no email whatever this field says

FieldTypeDescription
userAdmin user objectThe resulting account
StatusBodyCondition
200response bodyThe account was banned
404error responseUNKNOWN_USER, because the account does not exist

DISABLED is added to the account flags and temp_banned_until is set to the resolved expiry. Every authentication session is then deleted, so the account is signed out on every device.

An authentication attempt while the ban stands fails with 403 ACCOUNT_SUSPENDED_TEMPORARILY. An attempt after the expiry has passed clears the DISABLED flag and temp_banned_until in the same request, so a temporary ban ends without an Admin operation.

When notify_user is true, the account has an email address, and duration_hours is greater than zero, the account holder is emailed the duration, the expiry, and the supplied reason. A permanent ban sends no email. A failed email is logged and the ban still applies.

User Update is emitted after the sessions are deleted, so no connection of the account remains to receive it. DISABLED is not a public account flag, and no other account observes the change.

The operation records one Admin audit entry with action temp_ban, target type user, and the metadata keys duration_hours, reason, banned_until, notify_user, and notification_sent.

100 requests per minute for each authenticated user, on the admin:user:modify bucket.

DELETE/v1/admin/users/{user_id}/banAudit reason

Clears the account ban and returns the resulting account. Requires user:temp_ban.

FieldTypeDescription
user_idsnowflakeThe ID of the target account
FieldTypeDescription
notify_user?booleanWhether to email the account holder that the ban was lifted (default true)
public_reason?1stringStatement shown to the account holder in the email (at most 512 characters)

1 Also recorded in the audit entry. The X-Audit-Log-Reason value is never emailed

FieldTypeDescription
userAdmin user objectThe resulting account
StatusBodyCondition
2001response bodyThe ban was cleared
404error responseUNKNOWN_USER, because the account does not exist

1 The operation checks no precondition. On an account that was never banned it writes temp_banned_until as null, clears DISABLED, and sends no email

temp_banned_until is cleared and DISABLED is removed from the account flags.

Deleted sessions are not restored. Fluxer emails the account holder, with public_reason when one is supplied, only when notify_user is true, the ban was still in force, the account has an email address, and the account is neither closed nor pending deletion. A failed email is logged and the ban is still cleared. User Update is emitted to the account’s own sessions.

The operation records one Admin audit entry with action unban, target type user, and the metadata keys notify_user, notification_sent, and public_reason.

100 requests per minute for each authenticated user, on the admin:user:modify bucket.

POST/v1/admin/users/{user_id}/ban/notes

Appends a note to the ban that currently stands on the account. Requires user:temp_ban. The ban entry and earlier notes are never changed.

FieldTypeDescription
user_idsnowflakeThe ID of the target account
FieldTypeDescription
ban_audit_log_id1snowflakeThe ID of the temp_ban audit entry of the current ban
notestringThe note (1-512 characters)

1 The entry must target this account, and its banned_until metadata must equal the current temp_banned_until

StatusBodyCondition
204noneThe note was recorded
400error responseINVALID_FORM_BODY, because ban_audit_log_id does not name a ban of this account
404error responseUNKNOWN_USER, because the account does not exist
409error responseCONFLICT, because the named ban is no longer the current ban

The operation records one Admin audit entry with action annotate_ban, target type user, the note as audit_log_reason, and a metadata key ban_audit_log_id. The X-Audit-Log-Reason header is not read.

100 requests per minute for each authenticated user, on the admin:user:modify bucket.

PUT/v1/admin/users/{user_id}/deletionAudit reason

Creates an account deletion schedule and returns the resulting account. Requires user:delete. A pending schedule is replaced only when the request names it in replace_pending_deletion_at, and a schedule cannot be changed once erasure starts.

Fluxer raises the submitted delay to the minimum for the deletion reason, so a request for one day under any reason other than USER_REQUESTED is stored as 60 days.

The X-Audit-Log-Reason value is also stored on the account as the private deletion reason and reused as the blocklist reason for the identifier bans below.

FieldTypeDescription
user_idsnowflakeThe ID of the target account
FieldTypeDescription
reason_code1integerDeletion reason
public_reason?2stringStatement of reasons shown to the account holder (at most 512 characters)
days_until_deletion?3integerRequested whole-day delay (1-365, default 60)
replace_pending_deletion_at?4ISO8601 timestampThe pending_deletion_at of the schedule this request replaces
notify_user?booleanWhether to email the account holder about the scheduled deletion (default true)

1 Required, and validated against the deletion reason registry. USER_REQUESTED selects the 14-day minimum, and every other value selects the 60-day minimum

2 Stored on the account and included in the deletion email. Omitting it stores null

3 The stored deadline is the request instant plus the greater of this value and the minimum for the reason code. There is no absolute-timestamp field

4 Required when the account already has a pending deletion, including one the caller scheduled. It must equal the current pending_deletion_at

FieldTypeDescription
userAdmin user objectThe resulting account
StatusBodyCondition
200response bodyThe deletion schedule was stored
404error responseUNKNOWN_USER, because the account does not exist
409error responseCONFLICT, because a pending deletion was not named, erasure has started, or the deletion state changed

user:delete also allows scheduling deletion of the acting Admin or an account with broader permissions.

The account can no longer authenticate, and its existing authentication sessions and OAuth2 access and refresh tokens are deleted. The acting Admin and the time are stored as deletion_scheduled_by and deletion_scheduled_at. Erasure is scheduled for the resulting deadline.

Fluxer cancels a Stripe subscription on the account without proration and refunds the charge behind its latest invoice as fraudulent. When the cancellation or refund fails, Fluxer logs the failure and still keeps the deletion schedule.

The account holder is emailed the deadline and the supplied public_reason when notify_user is true and the account has an email address. The wording depends on reason_code: USER_REQUESTED and INACTIVITY get a neutral notice, and every other code gets an enforcement notice. A failed email is logged and the schedule is still stored.

For every reason other than USER_REQUESTED, Fluxer also blocks the account’s email address. For the reasons SPAM, CHEATING_OR_EXPLOITATION, COORDINATED_RAIDING, AUTOMATION_OR_SELFBOT, SCAM_OR_SOCIAL_ENGINEERING, HARASSMENT_OR_BULLYING, BAN_EVASION, TOKEN_OR_CREDENTIAL_SCAM, HATE_SPEECH_OR_EXTREMIST_CONTENT, MALICIOUS_LINKS_OR_MALWARE, and IMPERSONATION_OR_FAKE_IDENTITY, Fluxer also resolves the pending reports against the account. A pending report in the child_safety, underage_user, or self_harm category is left for a moderator and stays pending. Every other reason leaves all reports pending. These enforcement steps are best-effort and can fail without cancelling the deletion schedule.

User Update is emitted after the sessions have already been deleted. The operation records one Admin audit entry with action schedule_deletion, target type user, and the metadata keys days, reason_code, pending_deletion_at, notify_user, and notification_sent. An attempted email adds notification_template. A replacement adds replaced_pending_deletion_at, replaced_scheduled_by, replaced_scheduled_at, and replaced_reason_code for the schedule it replaced. The identifier bans record their own blocklist entries. For each reason that resolves reports, Fluxer also records a second entry with action auto_resolve_reports_on_deletion, target type user, and the metadata keys outcome, found_count, resolved_count, failed_count, and notified_count. found_count leaves out the reports in the three categories that stay pending. No such entry is written for any other reason. outcome is completed, search_unavailable when the instance has no report search backend and every report stays pending, or enumeration_failed when listing the pending reports failed part way and only those already found were resolved. Each resolved report sends its reporter the generic notice Update report describes, with no public comment.

100 requests per minute for each authenticated user, on the admin:user:modify bucket.

DELETE/v1/admin/users/{user_id}/deletionAudit reason

Cancels the scheduled deletion named in the request and returns the resulting account. Requires user:delete. Erasure cannot be cancelled once it starts.

FieldTypeDescription
user_idsnowflakeThe ID of the target account
FieldTypeDescription
expected_pending_deletion_at1ISO8601 timestampThe pending_deletion_at of the deletion being cancelled
notify_user?booleanWhether to email the account holder (default false)

1 Required. It must equal the current pending_deletion_at, so a cancel written against one schedule never clears a different one

FieldTypeDescription
userAdmin user objectThe resulting account
StatusBodyCondition
200response bodyThe deletion was cancelled
400error responseNO_PENDING_DELETION, because no deletion is scheduled
404error responseUNKNOWN_USER, because the account does not exist
409error responseCONFLICT, because a different deletion is pending, erasure has started, or the deletion state changed

The deletion schedule, its reasons, and the recorded scheduler are cleared, allowing the account to authenticate again unless another restriction applies.

When notify_user is true and the account has an email address, Fluxer emails the account holder. The email never includes the X-Audit-Log-Reason value.

User Update is emitted to the account’s own sessions. The operation records one Admin audit entry with action cancel_deletion, target type user, the metadata keys cancelled_pending_deletion_at, cancelled_scheduled_by, cancelled_scheduled_at, and cancelled_reason_code for the cancelled schedule, and notify_user.

100 requests per minute for each authenticated user, on the admin:user:modify bucket.

GET/v1/admin/users/{user_id}/guildsAudit reason

Lists the guilds the account is a member of, in ascending guild ID order. Requires user:list:guilds. Both cursors apply to the account’s own sorted membership list.

FieldTypeDescription
user_idsnowflakeThe ID of the target account
FieldTypeDescription
before?1snowflakeReturn guilds ordered before this guild ID
after?1snowflakeReturn guilds ordered after this guild ID
limit?integerMaximum guilds to return (1-200, default 200)
with_counts?2booleanWhether to resolve live member and presence counts (default false)

1 A cursor naming a guild the account is not a member of is ignored, and the request still succeeds. after is applied before before, and the two combine to bound a window

2 Only the exact strings true, True, and 1 count as true

FieldTypeDescription
guilds1array[Admin guild object]The guilds in this page that the account is a member of

1 approximate_member_count and approximate_presence_count are present only when with_counts resolved to true. owner_username, owner_global_name, and owner_discriminator are resolved by this operation and are null only for an owner account that no longer exists

StatusBodyCondition
200response bodyThe membership page was returned
404error responseUNKNOWN_USER, because the account does not exist

The response has no paging state. Derive the next cursor from the last returned guild ID, and treat a short page as the end of the list.

The operation records one Admin audit entry with action list_user_guilds, target type user, the path user_id as target ID, and the metadata keys limit, with_counts, and guild_count for the guilds returned. A supplied cursor adds before_guild_id or after_guild_id. A failed request records nothing.

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

GET/v1/admin/users/{user_id}/dm-channelsAudit reason

Lists the direct message channels the account has taken part in. Requires user:list:dm_channels. The read does not open, reopen, or acknowledge a channel for the target account.

The group branch ignores before, after, and limit, and returns every group the account is a recipient of in one response.

FieldTypeDescription
user_idsnowflakeThe ID of the target account
FieldTypeDescription
type?stringChannel class, either dm or group_dm (default dm)
before?1snowflakeReturn channels with IDs lower than this channel ID
after?1snowflakeReturn channels with IDs higher than this channel ID
limit?integerMaximum channels to return (1-200, default 50)

1 Mutually exclusive. Supplying both fails validation even when type is group_dm and neither would be used

FieldTypeDescription
channels1array[Admin direct message channel object]The channels in this page

1 Bounded at 200 entries for dm and at 500 entries for group_dm

StatusBodyCondition
200response bodyThe channel page was returned
404error responseUNKNOWN_USER, because the account does not exist

The response has no paging state. Derive the next cursor from the last returned channel ID.

The operation records one Admin audit entry with action list_user_dm_channels, target type user, the path user_id as target ID, and the metadata keys type and channel_count for the channels returned. A dm request also records limit, and before_channel_id or after_channel_id when a cursor is supplied. A 404 records nothing.

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

GET/v1/admin/users/{user_id}/applicationsAudit reason

Lists the OAuth2 applications the account owns. Requires application:lookup or application:list:by_owner, the same pair List applications accepts.

FieldTypeDescription
user_idsnowflakeThe ID of the owning account
FieldTypeDescription
applications1array[Admin application object]The applications the account owns

1 Returned in full in one response. The operation accepts no query string parameters and defines no cursor

StatusBodyCondition
200response bodyThe applications were returned
404error responseUNKNOWN_USER, because the account does not exist

The operation records one Admin audit entry with action list_user_applications, target type user, the path user_id as target ID, and a metadata key application_count. A 404 records nothing.

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

GET/v1/admin/users/{user_id}/relationshipsAudit reason

Lists the friends, friend requests, and blocked accounts of the account, split into one array for each relationship category. Requires user:list:relationships.

FieldTypeDescription
user_idsnowflakeThe ID of the target account
FieldTypeDescription
friends1array[Admin relationship object]The mutual friendships of the account
incoming_requests1array[Admin relationship object]The friend requests the account has received
outgoing_requests1array[Admin relationship object]The friend requests the account has sent
blocked1array[Admin relationship object]The accounts this account has blocked

1 A stored relationship type outside the categories is dropped from the response

The operation accepts no cursor, category filter, or limit, and returns every category in full.

StatusBodyCondition
200response bodyThe relationships were returned
404error responseUNKNOWN_USER, because the account does not exist

The operation records one Admin audit entry with action list_user_relationships, target type user, the path user_id as target ID, and the metadata keys friend_count, incoming_request_count, outgoing_request_count, and blocked_count. A 404 records nothing.

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

DELETE/v1/admin/users/{user_id}/relationshipsAudit reason

Removes every relationship of the account in one relationship category and returns the removed count. Requires user:remove:relationship.

category is required, so there is no request shape that clears every category at once.

FieldTypeDescription
user_idsnowflakeThe ID of the target account
FieldTypeDescription
category1stringRelationship category to clear

1 Required. There is no confirmation parameter and no dry-run mode

FieldTypeDescription
removed_count1integerThe number of relationships that were removed

1 Counted from the target account’s perspective, so a friendship, which both accounts store, contributes one

StatusBodyCondition
2001response bodyMatching relationships were removed
404error responseUNKNOWN_USER, because the account does not exist

1 A category with no matching relationship succeeds with a removed_count of zero, and still records the audit entry

Removals run one at a time, so a failure partway through leaves the earlier removals applied and answers 500.

Friendships and friend requests are removed for both accounts. Blocks are removed only for the target account.

When a friendship or friend request is removed, both accounts receive Relationship Remove naming the other account. A blocked removal dispatches only to the target account, and ordinary delivery from the unblocked account resumes.

The operation records one Admin audit entry with action remove_relationships_by_category, target type user, and the metadata keys category and removed_count.

100 requests per minute for each authenticated user, on the admin:user:modify bucket.

DELETE/v1/admin/users/{user_id}/relationships/{target_user_id}Audit reason

Removes one relationship row in one category. Requires user:remove:relationship. Returns an empty 204 response.

The operation addresses one category, so an account that is both a former friend and currently blocked needs two requests.

FieldTypeDescription
user_idsnowflakeThe ID of the account that owns the relationship
target_user_idsnowflakeThe ID of the other account
FieldTypeDescription
categorystringRelationship category to remove
StatusBodyCondition
204emptyThe relationship was removed
4041error responseUNKNOWN_USER, because the account does not exist

1 The same code covers an owning account that does not exist and a relationship that does not exist in the named category, so a 404 does not distinguish the two

A friendship or friend request is removed for both accounts. A block is removed only for the owning account.

When a friendship or friend request is removed, both accounts receive Relationship Remove naming the other account. A blocked removal dispatches only to the owning account.

The operation records one Admin audit entry with action remove_relationship, target type user, and the metadata keys target_user_id and category.

100 requests per minute for each authenticated user, on the admin:user:modify bucket.

GET/v1/admin/users/{user_id}/sessionsAudit reason

Lists the account’s active and terminated authentication sessions. Requires user:list:sessions. IP, reverse DNS and location fields also require user:view:ip.

FieldTypeDescription
user_idsnowflakeThe ID of the target account
FieldTypeDescription
sessions1array[Admin user session object]The active and terminated sessions of the account

1 Active sessions are listed before terminated ones, and each group is ordered by created_at descending. The operation accepts no cursor or limit and returns the complete list in one response

StatusBodyCondition
200response bodyThe sessions were returned
404error responseUNKNOWN_USER, because the account does not exist
5031error responseSERVICE_UNAVAILABLE when at least one session exists and every location lookup fails

1 Reachable only with user:view:ip, because no lookup is attempted without it. The audit entry is written after the lookups, so a request that fails this way records nothing

Without user:view:ip the derived fields are null and client_ip is the literal string [redacted], so a redacted address is distinguishable from a failed lookup. With it, a partial reverse DNS or location failure yields null for that field alone.

This read does not mutate session state and emits no Gateway Dispatch. It makes outbound reverse DNS and geolocation lookups for each session address when the caller holds user:view:ip.

The operation records one Admin audit entry with action list_user_sessions, target type user, and a metadata key session_count counting active and terminated sessions together.

100 requests per minute for each authenticated user, on the admin:user:modify bucket. The other lists on this resource use the admin:lookup read bucket.

DELETE/v1/admin/users/{user_id}/sessionsAudit reason

Terminates every active authentication session of the account. Requires user:update:flags, the same ACL as Update user flags.

There is no operation that revokes one session. The account’s Admin API keys, bot token, and OAuth2 tokens are separate credentials and are not affected.

FieldTypeDescription
user_idsnowflakeThe ID of the target account
StatusBodyCondition
2001terminate sessions responseActive sessions were terminated
404error responseUNKNOWN_USER, because the account does not exist

1 An account with no live session is accepted, returns terminated_count 0, and still records the audit entry

FieldTypeDescription
terminated_countintegerThe number of sessions that were terminated

Every affected client is disconnected and must authenticate again. Terminated sessions remain listed with deleted_at set.

The operation records one Admin audit entry with action terminate_sessions, target type user, and no metadata.

100 requests per minute for each authenticated user, on the admin:user:modify bucket.

GET/v1/admin/users/{user_id}/webauthn-credentialsAudit reason

Lists the passkeys and security keys registered on the account, as a bare JSON array. Requires user:update:mfa, the same ACL as Disable user MFA.

FieldTypeDescription
user_idsnowflakeThe ID of the target account
StatusBodyCondition
2001array[WebAuthn credential object]The credentials were returned
404error responseUNKNOWN_USER, because the account does not exist

1 An account with no credential receives an empty array

The complete credential set is returned in one response, bounded by the ten credentials an account may register. Replaced passkeys are left out, and credential_count counts only the returned ones. No public key, attestation object, or signature counter is exposed.

This read does not mutate authenticator state and emits no Gateway Dispatch. It records one Admin audit entry with action list_webauthn_credentials, target type user, and a metadata key credential_count.

100 requests per minute for each authenticated user, on the admin:user:modify bucket.

DELETE/v1/admin/users/{user_id}/webauthn-credentials/{credential_id}Audit reason

Deletes one passkey or security key from the account. Requires user:update:mfa. Returns an empty 204 response.

FieldTypeDescription
user_idsnowflakeThe ID of the target account
credential_idstringWebAuthn credential ID (1-512 characters)
StatusBodyCondition
204emptyThe credential was deleted
4041error responseUNKNOWN_USER, because the account does not exist

1 A credential that does not exist on the account also answers UNKNOWN_USER, so a 404 with that code does not distinguish an unknown account from an unknown credential. A replaced passkey answers UNKNOWN_WEBAUTHN_CREDENTIAL and records no audit entry

The credential record is deleted, together with the replaced passkeys it took over from, and every replaced passkey goes once no listed credential remains. When it was the account’s final WebAuthn credential and the account had enabled passkeys as a second factor, Fluxer removes the WEBAUTHN authenticator type from the account, emits User Update to the account’s own sessions, and copies the account’s authenticator types onto the bot user of every application the account owns. An account that never enabled passkeys as a second factor holds no WEBAUTHN type to remove.

WebAuthn Credentials Update is emitted to the target account with its remaining credentials.

The operation records one Admin audit entry with action delete_webauthn_credential, target type user, and a metadata key credential_id.

100 requests per minute for each authenticated user, on the admin:user:modify bucket.

DELETE/v1/admin/users/{user_id}/mfaAudit reason

Clears the account’s TOTP authenticator, its registered authenticator type set, and its backup codes. Requires user:update:mfa. Returns an empty 204 response.

FieldTypeDescription
user_idsnowflakeThe ID of the target account
StatusBodyCondition
204emptyMFA state was cleared
404error responseUNKNOWN_USER, because the account does not exist

The account’s TOTP secret, authenticator type set, and every multi-factor backup code are deleted. Fluxer clears the authenticator types of the bot user of every application the account owns. Sessions and credentials are not revoked.

User Update is emitted to the account’s own sessions. The operation records one Admin audit entry with action disable_mfa, target type user, and no metadata.

100 requests per minute for each authenticated user, on the admin:user:modify bucket.

DELETE/v1/admin/users/{user_id}/messagesAudit reason

Counts every message attributed to the account, and queues their deletion when the request is not a dry run. Requires message:delete_all.

The request counts messages before responding, so accounts with more messages take longer. A misspelled dry_run parameter leaves the request a dry run.

The operation does not resolve the target account, so it never answers UNKNOWN_USER. An ID with no matching account is accepted and matches no message.

FieldTypeDescription
user_idsnowflakeThe ID of the message author
FieldTypeDescription
dry_run?1stringWhether the operation only counts matching messages (default true)

1 Whitespace is trimmed and only the exact values false, False, and 0 count as false. Every other string, including no and FALSE, counts as true

FieldTypeDescription
successbooleanWhether the request succeeded, always true
dry_runbooleanWhether the request only counted messages
channel_count1integerThe number of channels the account has messages in
message_countintegerThe number of messages the walk matched
job_id?2stringThe ID of the queued shred job

1 Summed for each page of 200, so a channel spanning pages is counted once per page. Treat it as an upper bound

2 Present only when dry_run resolved to false and message_count is above zero

StatusBodyCondition
200response bodyThe count completed, and the deletion job was queued when applicable

The queued job is an ordinary shred job, so its progress, totals, skips, and failures are read through Get message shred job.

A dry run reads and counts only. A deletion run also queues one shred job with every matched message identity, and the request returns before any message is processed.

The operation records one Admin audit entry with target type message_deletion, the target account ID as its target ID, and the metadata keys user_id, channel_count, message_count, and dry_run. The action is delete_all_user_messages_dry_run for a dry run and delete_all_user_messages otherwise. A deletion run also records the queue_message_shred entry described under Shred user messages.

100 requests per minute for each authenticated user, on the admin:message:operation bucket.

POST/v1/admin/users/{user_id}/message-shredsAudit reason

Queues irreversible deletion of an explicit list of message identities and returns a job ID read through Get message shred job. Requires message:shred.

The operation does not resolve the target account, so it never answers UNKNOWN_USER.

FieldTypeDescription
user_idsnowflakeThe ID of the message author
FieldTypeDescription
entries1array[message shred entry object]Explicit message identities, with 1 to 1000 values

1 Required and non-empty. The entries are not checked against the target account at submission time

FieldTypeDescription
successbooleanWhether the request succeeded, always true
job_idstringThe ID of the queued shred job
requested1integerThe number of submitted entries

1 An upper bound on the messages the job shreds

StatusBodyCondition
200response bodyThe shred job was queued

A failed job is not retried automatically.

The request returns before any message is processed. The job checks each referenced message again before it deletes it, and skips a missing message or one no longer authored by the target account.

The operation records one Admin audit entry with action queue_message_shred, target type message_shred, the target account ID as its target ID, and the metadata keys user_id, job_id, and requested_entries.

100 requests per minute for each authenticated user, on the admin:message:operation bucket.

DELETE/v1/admin/users/{user_id}/message-deletionAudit reason

Cancels the bulk message deletion the account holder scheduled for itself and returns the resulting account. Requires user:cancel:bulk_message_deletion.

Delete all user messages queues a separate Admin job over the same messages, and cancelling this schedule leaves that job running.

FieldTypeDescription
user_idsnowflakeThe ID of the target account
FieldTypeDescription
userAdmin user objectThe resulting account
StatusBodyCondition
2001response bodyThe scheduled deletion was cancelled, or the account had none
404error responseUNKNOWN_USER, because the account does not exist

1 The operation is idempotent. Calling it on an account with no scheduled deletion succeeds, returns the account unchanged, and still records the audit entry

pending_bulk_message_deletion_at is cleared together with the stored channel and message counts, and the account is removed from the bulk deletion queue, so no further message is deleted. Messages already deleted by an earlier run are not restored.

No User Update is emitted, unlike every other mutating user operation on this page, so a connected client learns of the cancellation only on its next read. The operation records one Admin audit entry with action cancel_bulk_message_deletion, target type user, and no metadata.

100 requests per minute for each authenticated user, on the admin:user:modify bucket.

POST/v1/admin/users/{user_id}/archivesAudit reason

Creates an asynchronous archive of the account’s data and returns the created archive object. Requires archive:trigger:user.

Archive progress, download, and expiry are documented under Archives.

FieldTypeDescription
user_idsnowflakeThe ID of the archive subject
FieldTypeDescription
include_attachments?1booleanWhether uploaded files are included (default false)

1 Including attachment binaries makes the archive larger and slower to build, and only an archive that includes them retains the original uploaded media

StatusBodyCondition
2001archive objectThe archive was queued
404error responseUNKNOWN_USER, and no archive record or build job is created

1 The archive starts with progress_percent at zero and progress_step set to Queued

Fluxer creates the archive record and queues a build job, so the response returns before any data is collected. Generating the archive reads the account’s data without changing it.

No Gateway Dispatch is emitted.

The operation records one Admin audit entry with action trigger_user_archive, target type user, the path user_id as target ID, and the metadata keys archive_id for the created archive and include_attachments as true or false.

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

GET/v1/admin/users/{user_id}/change-logAudit reason

Lists the identity and contact field changes recorded for the account, newest first. Requires user:view:contact_log. Email values also require user:view:email.

FieldTypeDescription
user_idsnowflakeThe ID of the target account
FieldTypeDescription
limit?integerMaximum entries to return (1-200, default 50)
page_token?1stringCursor returned as next_page_token by the previous page (1-64 characters)

1 Continues the newest-first walk, so it returns entries recorded before the cursor

FieldTypeDescription
entries1array[Admin user change log object]The identity and contact changes in this page
next_page_token2?stringThe cursor to send as page_token, or null when this is the last page

1 Bounded at 200 entries, which is also the maximum limit

2 Set only when the page returned exactly limit entries, so a final page that happens to be full reports a cursor whose next page is empty

StatusBodyCondition
2001response bodyThe change page was returned

1 This operation does not resolve the account, so it never answers UNKNOWN_USER. An ID with no matching account returns an empty page

Without user:view:email, an email entry is still returned with both value fields replaced by the literal string [redacted], so the fact and the time of the change stay visible while the addresses do not.

The operation records one Admin audit entry with action list_user_change_log, target type user, the path user_id as target ID, and the metadata keys limit and entry_count for the entries returned. A supplied page_token adds has_page_token as true, and the cursor value is not recorded.

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