Skip to content
Fluxer API

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.

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.

FieldTypeDescription
job_idsnowflakeThe ID of the job
task_typestringThe background job task type the job runs
statusstringThe job status the row currently holds
progress_current1?integerThe units of work completed, or null when the task has reported none
progress_total1?integerThe units of work expected, or null when the task has reported none or reported no total
progress_message1?stringThe step the task last reported, or null when it has reported none
error_message2?stringThe failure text recorded when the job was dead-lettered, or null otherwise
created_atISO8601 timestampThe time the job was written to the ledger
started_at3?ISO8601 timestampThe time the most recent execution began, or null before the first attempt
completed_at?ISO8601 timestampThe time the job reached a terminal state, or null while it is not terminal
requested_by_user_id4?snowflakeThe ID of the account recorded as the requester, or null when the queueing operation recorded none
audit_log_reason5?stringThe reason recorded when the job was queued, or null when none was supplied
jet_stream_lane6?stringThe processing lane the job runs on, or null when no lane claims the task type
jet_stream_seq?stringThe stream sequence assigned when the job was published, as a decimal string
attempts7integerThe number of failed executions recorded so far
max_attempts8integerThe attempt budget captured when the job was queued
run_at?ISO8601 timestampThe earliest permitted run time, or null for an immediate job
cancel_requested9booleanWhether cooperative cancellation has been requested
context_link10?stringThe Admin console path for the entities the job acts on, or null when the task set none
payload11?stringThe JSON rendering of the job input
result?stringAlways 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

{
"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
}

The resume point List jobs returns, split into the three cursor query parameters a caller sends back.

FieldTypeDescription
bucket_daystringThe UTC day bucket the next page resumes in, as YYYY-MM-DD
created_atISO8601 timestampThe creation time the next page resumes before
job_idsnowflakeThe job the next page resumes from
{
"bucket_day": "2026-08-30",
"created_at": "2026-08-30T22:41:07.512Z",
"job_id": "1500901337221828608"
}
ValueDescription
queuedThe job is written and available for processing
runningThe job is being processed
succeededThe task returned without throwing
cancelled1The task reached a cancellation checkpoint and aborted
deadletterThe 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.

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.

ValueDescription
realtime1Mention fan-out. Concurrency 10, 15 second deadline, 3 deliveries
unfurl1Link preview extraction. Concurrency 20, 30 second deadline, 3 deliveries
lifecycle1Account, guild, billing, moderation, archive, and bulk work. Concurrency 8, 60 second deadline, 25 deliveries
batch1Periodic 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

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.

  • realtime runs handleMentions and handleMentionChunk.
  • unfurl runs extractEmbeds.
  • lifecycle runs applicationProcessDeletion, batchGuildAuditLogMessageDeletes, bulkAddGuildMembers, bulkBanFileShas, bulkDeleteSelfMessagesImmediate, bulkDeleteUserMessages, bulkDeleteUserMessagesScoped, bulkScheduleUserDeletion, bulkUpdateGuildFeatures, bulkUpdateSuspiciousActivityFlags, bulkUpdateUserFlags, deleteUserMessagesInGuildByTime, finalizeNcmecAttachmentReport, harvestGuildData, harvestUserData, messageShred, processStripeWebhook, reconcileUserPayments, revalidateUserConnections, sendSystemDm, userProcessPendingDeletion, and userProcessPendingDeletions.
  • batch runs expireAttachments, flushUserActivityBuffer, indexChannelMessages, indexGuildMembers, processAssetDeletionQueue, processBunnyPurgeQueue, processExpiredPremiumSweep, processInactivityDeletions, processPendingBulkMessageDeletions, processPremiumStateReconciliationQueue, prunePostgresKvTtl, refreshSearchIndex, syncDiscoveryIndex, syncDisposableEmailDomains, syncFileShaBlocklists, and syncUrlBlocklists.

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.

GET/v1/admin/jobs

Returns 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.

FieldTypeDescription
limit?integerThe maximum number of jobs to return (1-200, default 50)
cursor_bucket_day?1stringThe UTC day bucket to resume from as a YYYY-MM-DD date, taken from next_cursor.bucket_day
cursor_created_at?1stringThe creation time to resume before as an ISO 8601 timestamp (1-64 characters), taken from next_cursor.created_at
cursor_job_id?1snowflakeThe job to resume from, taken from next_cursor.job_id
max_lookback_days?2integerThe number of earlier day buckets to scan (1-60, default 14)
status?stringThe job status a returned job must currently hold
task_type?3stringThe background job task type a returned job must run (1-128 characters)
requested_by_user_id?snowflakeThe 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

FieldTypeDescription
jobsarray[Admin job object]The jobs in this page
next_cursor?job cursor objectThe cursor for the next page, or null when the page did not fill
StatusBodyCondition
200response bodyThe job page was returned
400error responseINVALID_FORM_BODY because the cursor is a strict subset of its three parts or one part is malformed

600 requests per minute for each authenticated user, on the admin:jobs:view bucket.

GET/v1/admin/jobs/active

Returns 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.

FieldTypeDescription
jobsarray[Admin job object]Every queued or running job the index holds
StatusBodyCondition
200response bodyThe active jobs were returned

600 requests per minute for each authenticated user, on the admin:jobs:view bucket.

GET/v1/admin/jobs/{job_id}

Returns one Admin job object. Requires jobs:view.

FieldTypeDescription
job_idsnowflakeThe ID of the job
FieldTypeDescription
jobAdmin job objectThe job
StatusBodyCondition
200response bodyThe 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

600 requests per minute for each authenticated user, on the admin:jobs:view bucket.

PUT/v1/admin/jobs/{job_id}/cancellation

Requests cooperative cancellation of a job and reports whether the request was recorded. Requires jobs:cancel.

FieldTypeDescription
job_idsnowflakeThe ID of the job
FieldTypeDescription
cancelled1booleanWhether 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

StatusBodyCondition
200response bodyThe request was evaluated, whether or not the flag changed

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.

600 requests per minute for each authenticated user, on the admin:jobs:view bucket.