Bulk jobs
A bulk job applies one operation to an explicit set of users or guilds. The task field selects the request body and required Admin ACL.
Every target is a list of IDs. There is no search, role, tag, email, or IP selector, so the caller resolves its own target set first with List users or List guilds.
Queue bulk job returns a job identifier immediately and applies nothing synchronously. The caller reads progress, terminal state, and failure text through Get job. Cancel job stops a run.
Bulk job creation object
Section titled “Bulk job creation object”A bulk job creation has the identifier of the queued job.
Structure
Section titled “Structure”| Field | Type | Description |
|---|---|---|
| job_id1 | snowflake | The job that applies the requested operation, readable through Get job |
1 The job is readable as soon as this response arrives
Example
Section titled “Example”{ "job_id": "1501314428688998182"}Bulk task types
Section titled “Bulk task types”Each value is the exact task discriminator.
update_user_flags
Section titled “update_user_flags”ACL bulk:update:user_flags. Adds and removes account flags on every targeted user. Runs as bulkUpdateUserFlags.
update_guild_features
Section titled “update_guild_features”ACL bulk:update:guild_features. Adds and removes features on every targeted guild. Runs as bulkUpdateGuildFeatures.
add_guild_members
Section titled “add_guild_members”ACL bulk:add:guild_members. Adds every targeted user to one guild. Runs as bulkAddGuildMembers.
schedule_user_deletion
Section titled “schedule_user_deletion”ACL bulk:delete:users. Closes every targeted account and schedules its deletion. Runs as bulkScheduleUserDeletion. A job queued in the shape used before enforcement decisions, with reason_code and no basis, fails when the worker runs it instead of inventing a decision.
delete_user_messages
Section titled “delete_user_messages”ACL bulk:delete:user_messages. Deletes every message each targeted account wrote. Runs as bulkDeleteMessagesForUsers. A job queued without a basis fails when the worker runs it.
Each worker task is recorded as task_type on the job and listed under background job task types. Every bulk task runs in the lifecycle processing lane.
Queue bulk job
Section titled “Queue bulk job”POST/v1/admin/bulk-jobsQueues one bulk operation. Returns a bulk job creation object on success.
Limitations
Section titled “Limitations”- The body matches exactly one
taskvariant. - The caller needs at least one of the bulk ACLs and then the exact ACL that
taskselects.
JSON body
Section titled “JSON body”The task discriminator selects one of these structures. Every ID array has an upper bound and no lower bound, so an empty array queues a job that processes nothing and finishes with the status succeeded.
Update user flags structure
Section titled “Update user flags structure”| Field | Type | Description |
|---|---|---|
| task | string | The discriminator selecting this variant, update_user_flags |
| user_ids | array[snowflake] | The users to update (max 1000 entries) |
| add_flags?1 | array[string] | Account flag values to add (max 64, default empty) |
| remove_flags?1 | array[string] | Account flag values to remove (max 64, default empty) |
1 Each entry is one 64-bit flag value written as an unsigned decimal string, such as 1024. Body validation rejects a symbolic name. Additions are applied before removals, so a value named in both arrays ends up cleared
Update guild features structure
Section titled “Update guild features structure”| Field | Type | Description |
|---|---|---|
| task | string | The discriminator selecting this variant, update_guild_features |
| guild_ids | array[snowflake] | The guilds to update (max 1000 entries) |
| add_features?1 | array[string] | Guild features to add (max 100, default empty) |
| remove_features?1 | array[string] | Guild features to remove (max 100, default empty) |
1 Body validation accepts any string, so a name outside the registry is written to the guild’s feature set. Additions are applied before removals
Add guild members structure
Section titled “Add guild members structure”| Field | Type | Description |
|---|---|---|
| task | string | The discriminator selecting this variant, add_guild_members |
| guild_id | snowflake | The guild that receives the users |
| user_ids | array[snowflake] | The users to add as members (max 1000 entries) |
Schedule user deletion structure
Section titled “Schedule user deletion structure”| Field | Type | Description |
|---|---|---|
| task | string | The discriminator selecting this variant, schedule_user_deletion |
| user_ids | array[snowflake] | The users to schedule for deletion (max 1000 entries) |
| days_until_deletion1 | integer | The delay before deletion in whole days (1-365) |
| basis2 | basis object | Why the accounts are closed |
1 Fluxer raises the value to the minimum of the basis, 74 days for a broken rule and 14 days otherwise. A self-hosted instance has no appeal route and raises every basis to 14 days
2 The enforcement basis takes a bulk decision with reason_code, source (always own_review), automation and a required statement. Reports, evidence messages and any other field are refused, because per-account facts cannot be given in bulk. The X-Audit-Log-Reason header is required with this basis, or the request fails with ENFORCEMENT_INTERNAL_NOTE_REQUIRED, and becomes the first note on every decision
Delete user messages structure
Section titled “Delete user messages structure”| Field | Type | Description |
|---|---|---|
| task | string | The discriminator selecting this variant, delete_user_messages |
| user_ids | array[snowflake] | The users whose messages are deleted (max 1000 entries) |
| basis1 | basis object | Why the messages are deleted |
1 Takes the same bulk decision and X-Audit-Log-Reason rule as the schedule user deletion structure. A reason with restricted handling is refused for each account, because it needs evidence messages
Response
Section titled “Response”| Status | Body | Condition |
|---|---|---|
| 200 | bulk job creation object | The bulk job was queued |
| 400 | error response | INVALID_FORM_BODY, including for a restriction flag or a missing internal note |
| 403 | error response | MISSING_ACL without the ACL selected by task |
| 5001 | error response | The job could not be queued |
1 A full queue rejects the job and the request returns INTERNAL_SERVER_ERROR
Side effects
Section titled “Side effects”The job records the acting Admin and audit reason. Queueing records one Admin audit entry with action queue_bulk_job, target type bulk_job, target ID equal to the job identifier, and metadata keys task and entity_count. entity_count is the length of guild_ids for update_guild_features and of user_ids for every other task. An add_guild_members entry also has guild_id. Failure to create the job returns 500 INTERNAL_SERVER_ERROR without starting the operation or recording an entry.
Entities are processed in the submitted order. Cancel job stops the run between entities and sets its status to cancelled. Completed changes remain in place. A failed or unknown entity counts as failed without stopping the remaining work.
Every task updates its progress before work starts and at completion. Every task except schedule_user_deletion also updates its progress after every 25 entities, and schedule_user_deletion updates its progress after every 10 accounts. The final progress_message has the successful and failed counts.
Every task writes one summary Admin audit entry when it finishes, with the action bulk_update_user_flags, bulk_update_guild_features, bulk_add_guild_members, bulk_schedule_deletion, bulk_ban_file_shas, or bulk_delete_user_messages. The summary has the audit reason, the entity count, the operation-specific parameters, the job identifier, and the processed, successful, and failed counts. Its target_type is bulk_job and its target_id is the job identifier, except for add_guild_members, which targets the guild. A failed job writes no summary entry. A cancelled job writes one, marked cancelled, covering the entities it processed before it stopped.
update_user_flags refuses the same restriction flag changes as Update user flags. Adding one fails the request with FLAG_REQUIRES_ENFORCEMENT_ROUTE, and a removal an account refuses counts that account as failed. It writes one update_flags entry for each account and dispatches User Update to the account’s sessions. A change to a publicly visible flag also dispatches Guild Member Update to every guild the account is in.
update_guild_features writes one update_features entry for each guild, dispatches Guild Update, and reindexes the guild for search. Fluxer reconciles a guild that already has a discovery application record against the new feature set, so gaining DISCOVERABLE approves the record and losing it marks the record removed. A guild with no discovery record is left alone.
add_guild_members bypasses the ban check that a normal join runs. The task suppresses the join system message, records the join source as an Admin force add, and dispatches Guild Member Add to the guild and Guild Create to the added account’s sessions. The task still enforces the per-account guild cap and the guild member cap, so an account at either ceiling is counted as failed. An account that is already a member is left unchanged and counted as successful, with no second membership and no Dispatch. Adding a bot account also records a BOT_ADD guild audit log entry attributed to the acting Admin.
delete_user_messages runs the same steps as Delete all user messages for each account, with the job’s basis. With the enforcement basis each account that wrote any message gets its own content removal decision and notice. Each account writes one delete_all_user_messages entry with the audit reason, the basis and the message count, and the summary entry records basis, plus reason_code for the enforcement basis. Progress is reported after every account.
schedule_user_deletion runs the same steps as Schedule user deletion for each account, with the job’s basis. With the enforcement basis each account gets its own decision and notice, its email is blocked when the rule bars new accounts, and the pending reports against it are resolved for the reasons that resolve reports, leaving the child_safety, underage_user, and self_harm categories pending. Each account writes one schedule_deletion entry with the audit reason, and the summary entry records basis, plus reason_code for the enforcement basis. A failed email is logged and does not fail the entity. An account that already has a pending deletion, or that a decision owns for a holder request or housekeeping deletion, counts as failed.
Rate limit
Section titled “Rate limit”20 requests per minute for each authenticated user, on the admin:bulk:operation bucket.