Jobs
The job ledger is Fluxer’s record of the background work an instance runs. An entry reports lifecycle state, progress, attempt accounting, payload, and terminal failure text. Nothing here creates a job. The operation that needs the work queues it, such as Queue bulk job, Create system DM broadcast, Refresh search index, or an archive request.
Reads require jobs:view and cancellation requires jobs:cancel. Every operation on this page shares the admin:jobs:view bucket.
Admin job object
Section titled “Admin job object”One object is one row of the ledger. No operation on this page changes any field except cancel_requested. A row has a 90 day time to live, after which the job is unknown to every operation here.
Structure
Section titled “Structure”| Field | Type | Description |
|---|---|---|
| job_id | snowflake | The ID of the job |
| task_type | string | The background job task type the job runs |
| status | string | The job status the row currently holds |
| progress_current1 | ?integer | The units of work completed, or null when the task has reported none |
| progress_total1 | ?integer | The units of work expected, or null when the task has reported none or reported no total |
| progress_message1 | ?string | The step the task last reported, or null when it has reported none |
| error_message2 | ?string | The failure text recorded when the job was dead-lettered, or null otherwise |
| created_at | ISO8601 timestamp | The time the job was written to the ledger |
| started_at3 | ?ISO8601 timestamp | The time the most recent execution began, or null before the first attempt |
| completed_at | ?ISO8601 timestamp | The time the job reached a terminal state, or null while it is not terminal |
| requested_by_user_id4 | ?snowflake | The ID of the account recorded as the requester, or null when the queueing operation recorded none |
| audit_log_reason5 | ?string | The reason recorded when the job was queued, or null when none was supplied |
| jet_stream_lane6 | ?string | The processing lane the job runs on, or null when no lane claims the task type |
| jet_stream_seq | ?string | The stream sequence assigned when the job was published, as a decimal string |
| attempts7 | integer | The number of failed executions recorded so far |
| max_attempts8 | integer | The attempt budget captured when the job was queued |
| run_at | ?ISO8601 timestamp | The earliest permitted run time, or null for an immediate job |
| cancel_requested9 | boolean | Whether cooperative cancellation has been requested |
| context_link10 | ?string | The Admin console path for the entities the job acts on, or null when the task set none |
| payload11 | ?string | The JSON rendering of the job input |
| result | ?string | Always null |
1 The task reports progress at its own cadence, and a task that never reports leaves all three null for its whole run. A bulk task reports once before it starts, again after every 25 entities, and once when it finishes, except for schedule_user_deletion, which reports after every 10 accounts, and the file SHA bulk ban, which reports after every 50 hashes
2 Written only when the job is dead-lettered. A single failed delivery that is redelivered leaves it null
3 Rewritten on every delivery, so a redelivered job reports the start of its latest attempt
4 Only Queue bulk job and the file SHA bulk ban record one, so a system DM broadcast, an archive, and a search index rebuild all report null
5 The reason the queueing operation resolved from X-Audit-Log-Reason. A blank or over-length header resolves to null there, and the queueing operation still succeeds
6 Present as soon as the job is queued
7 Incremented only when an attempt fails without exhausting the lane’s redelivery ceiling. A job that succeeds on its first delivery reports 0, and a dead-lettered job never counts its final failure
8 Defaults to 5 and is recorded for reporting only. The processing lane bounds redelivery
9 Set by Cancel job while the job is queued or running, and kept on the terminal row as the record of the request. status reports whether the task honoured it
10 An Admin console path such as /guilds/{guild_id}, not a Fluxer API route. A bulk task acting on many entities links only the first 50 identifiers
11 Stored verbatim as JSON, so it can contain identifiers and message content. It is returned by every operation here, including the listings
Example
Section titled “Example”{ "job_id": "1501314428688998182", "task_type": "bulkUpdateUserFlags", "status": "running", "progress_current": 25, "progress_total": 400, "progress_message": "Updating flags", "created_at": "2026-08-31T09:00:00.000Z", "started_at": "2026-08-31T09:00:01.000Z", "requested_by_user_id": "1478812292088791040", "jet_stream_lane": "lifecycle", "attempts": 0, "max_attempts": 5, "cancel_requested": false, "payload": "{\"user_ids\":[\"1478812292088791040\"]}", "result": null}Job cursor object
Section titled “Job cursor object”The resume point List jobs returns, split into the three cursor query parameters a caller sends back.
Structure
Section titled “Structure”| Field | Type | Description |
|---|---|---|
| bucket_day | string | The UTC day bucket the next page resumes in, as YYYY-MM-DD |
| created_at | ISO8601 timestamp | The creation time the next page resumes before |
| job_id | snowflake | The job the next page resumes from |
Example
Section titled “Example”{ "bucket_day": "2026-08-30", "created_at": "2026-08-30T22:41:07.512Z", "job_id": "1500901337221828608"}Job statuses
Section titled “Job statuses”| Value | Description |
|---|---|
| queued | The job is written and available for processing |
| running | The job is being processed |
| succeeded | The task returned without throwing |
| cancelled1 | The task reached a cancellation checkpoint and aborted |
| deadletter | The job exhausted its lane’s redelivery ceiling without succeeding |
1 Only a task that aborts at the checkpoint settles here, as Cancel job describes
queued and running are the active statuses and the other three are terminal. List active jobs returns exactly the two active statuses. Cancellation is recorded only while a job holds one of them.
A job whose queue publish fails after its ledger row is written also settles as deadletter. That row reports attempts 0, started_at null, and error_message from the publish failure.
Processing lanes
Section titled “Processing lanes”A lane is a consumer group with its own concurrency, acknowledgement deadline, and redelivery ceiling. Each task type belongs to exactly one lane, recorded on the job when it is queued.
| Value | Description |
|---|---|
| realtime1 | Mention fan-out. Concurrency 10, 15 second deadline, 3 deliveries |
| unfurl1 | Link preview extraction. Concurrency 20, 30 second deadline, 3 deliveries |
| lifecycle1 | Account, guild, billing, moderation, archive, and bulk work. Concurrency 8, 60 second deadline, 25 deliveries |
| batch1 | Periodic sweeps, index rebuilds, and queue drains. Concurrency 12, 120 second deadline, 25 deliveries |
1 Concurrency is per worker process and an operator can override it per lane. The delivery count bounds retries and is the ceiling after which a failing job is dead-lettered
Background job task types
Section titled “Background job task types”task_type is the registered worker task name. Every registered task is listed here with its lane, and a task that is not listed is not registered.
realtimerunshandleMentionsandhandleMentionChunk.unfurlrunsextractEmbeds.lifecyclerunsapplicationProcessDeletion,batchGuildAuditLogMessageDeletes,bulkAddGuildMembers,bulkBanFileShas,bulkDeleteSelfMessagesImmediate,bulkDeleteUserMessages,bulkDeleteUserMessagesScoped,bulkScheduleUserDeletion,bulkUpdateGuildFeatures,bulkUpdateSuspiciousActivityFlags,bulkUpdateUserFlags,deleteUserMessagesInGuildByTime,finalizeNcmecAttachmentReport,harvestGuildData,harvestUserData,messageShred,processStripeWebhook,reconcileUserPayments,revalidateUserConnections,sendSystemDm,userProcessPendingDeletion, anduserProcessPendingDeletions.batchrunsexpireAttachments,flushUserActivityBuffer,indexChannelMessages,indexGuildMembers,processAssetDeletionQueue,processBunnyPurgeQueue,processExpiredPremiumSweep,processInactivityDeletions,processPendingBulkMessageDeletions,processPremiumStateReconciliationQueue,prunePostgresKvTtl,refreshSearchIndex,syncDiscoveryIndex,syncDisposableEmailDomains,syncFileShaBlocklists, andsyncUrlBlocklists.
The five tasks queued by Bulk jobs are bulkUpdateUserFlags, bulkUpdateSuspiciousActivityFlags, bulkUpdateGuildFeatures, bulkAddGuildMembers, and bulkScheduleUserDeletion. harvestUserData and harvestGuildData build archives, sendSystemDm delivers a system DM broadcast, and refreshSearchIndex rebuilds a search index.
List jobs
Section titled “List jobs”GET/v1/admin/jobsReturns a page of Admin job objects from the ledger’s day buckets, newest first. Requires jobs:view.
The ledger is bucketed by UTC day and each bucket is ordered by creation time descending. A request reads the current bucket, then each earlier bucket, until the page is full or the lookback window is exhausted.
Query parameters
Section titled “Query parameters”| Field | Type | Description |
|---|---|---|
| limit? | integer | The maximum number of jobs to return (1-200, default 50) |
| cursor_bucket_day?1 | string | The UTC day bucket to resume from as a YYYY-MM-DD date, taken from next_cursor.bucket_day |
| cursor_created_at?1 | string | The creation time to resume before as an ISO 8601 timestamp (1-64 characters), taken from next_cursor.created_at |
| cursor_job_id?1 | snowflake | The job to resume from, taken from next_cursor.job_id |
| max_lookback_days?2 | integer | The number of earlier day buckets to scan (1-60, default 14) |
| status? | string | The job status a returned job must currently hold |
| task_type?3 | string | The background job task type a returned job must run (1-128 characters) |
| requested_by_user_id? | snowflake | The ID of the account a returned job must record as its requester |
1 The three cursor parameters are one value split into parts and are supplied together. A strict subset, a cursor_bucket_day that is not a calendar date, or a cursor_created_at that is not an ISO 8601 timestamp returns 400 INVALID_FORM_BODY, and each rejected part is named by the path of an element in errors
2 The scan covers the starting bucket plus this many earlier buckets, so the default reads 15. The starting bucket is the current UTC day, or the cursor’s bucket when one is supplied
3 A value naming no registered task returns an empty page with 200
Response body
Section titled “Response body”| Field | Type | Description |
|---|---|---|
| jobs | array[Admin job object] | The jobs in this page |
| next_cursor | ?job cursor object | The cursor for the next page, or null when the page did not fill |
Response
Section titled “Response”| Status | Body | Condition |
|---|---|---|
| 200 | response body | The job page was returned |
| 400 | error response | INVALID_FORM_BODY because the cursor is a strict subset of its three parts or one part is malformed |
Rate limit
Section titled “Rate limit”600 requests per minute for each authenticated user, on the admin:jobs:view bucket.
List active jobs
Section titled “List active jobs”GET/v1/admin/jobs/activeReturns every queued or running job as Admin job objects. Requires jobs:view.
A job still active after its ledger row has passed the 90 day time to live is omitted from the response.
Response body
Section titled “Response body”| Field | Type | Description |
|---|---|---|
| jobs | array[Admin job object] | Every queued or running job the index holds |
Response
Section titled “Response”| Status | Body | Condition |
|---|---|---|
| 200 | response body | The active jobs were returned |
Rate limit
Section titled “Rate limit”600 requests per minute for each authenticated user, on the admin:jobs:view bucket.
Get job
Section titled “Get job”GET/v1/admin/jobs/{job_id}Returns one Admin job object. Requires jobs:view.
Path parameters
Section titled “Path parameters”| Field | Type | Description |
|---|---|---|
| job_id | snowflake | The ID of the job |
Response body
Section titled “Response body”| Field | Type | Description |
|---|---|---|
| job | Admin job object | The job |
Response
Section titled “Response”| Status | Body | Condition |
|---|---|---|
| 200 | response body | The job was returned |
| 4041 2 | {"error": "job_not_found"} | No ledger entry has this identifier |
1 This operation answers a missing job with its own single-field body, so it has no code and no errors
2 A job queued with the ledger suppressed and a job whose row has passed its 90 day time to live are both reported this way, so 404 does not mean the work never ran
Rate limit
Section titled “Rate limit”600 requests per minute for each authenticated user, on the admin:jobs:view bucket.
Cancel job
Section titled “Cancel job”PUT/v1/admin/jobs/{job_id}/cancellationRequests cooperative cancellation of a job and reports whether the request was recorded. Requires jobs:cancel.
Path parameters
Section titled “Path parameters”| Field | Type | Description |
|---|---|---|
| job_id | snowflake | The ID of the job |
Response body
Section titled “Response body”| Field | Type | Description |
|---|---|---|
| cancelled1 | boolean | Whether a cancellation request was recorded |
1 False when the job is already terminal and also when no ledger entry has the identifier, so a false value does not distinguish the two. Cancelling a job that is already cancel-requested returns true again
Response
Section titled “Response”| Status | Body | Condition |
|---|---|---|
| 200 | response body | The request was evaluated, whether or not the flag changed |
Side effects
Section titled “Side effects”An active job records cancel_requested as true and stops at its next checkpoint. Fluxer leaves a terminal job unchanged. Nothing reverses the Gateway Dispatches the job already produced.
Rate limit
Section titled “Rate limit”600 requests per minute for each authenticated user, on the admin:jobs:view bucket.