Tasks

Run apps and manage tasks.


Run Task

POST /run

Run an app and optionally wait for completion.

Request

FieldTypeRequiredDescription
appstringYesApp identifier (namespace/name@version)
inputobjectYesInput data matching app schema
setupobjectNoSetup parameters
infrastringNo"cloud", "private", or "private_first" (default "cloud" when omitted)
workersstring[]NoSpecific worker IDs
webhookstringNoURL to receive a POST when the task completes
sessionstringNo"new" to start a session, or existing session ID
session_timeoutnumberNoSession idle timeout in seconds (1-3600, only with session: "new")

Example:

json
1{2  "app": "infsh/flux",3  "input": {4    "prompt": "A sunset over mountains"5  },6  "setup": {7    "model": "schnell"8  }9}

Response

FieldTypeDescription
idstringTask ID
statusnumberStatus code
inputobjectInput data
outputobjectOutput data (when complete). Internal pricing field output_meta is stripped — app authors still set it in app code; see Output metadata.
errorstringError message (if failed)
session_idstringSession ID (if using sessions)
created_atstringISO timestamp

Example:

json
1{2  "id": "task_abc123",3  "status": 10,4  "input": { "prompt": "A sunset..." },5  "output": {6    "image": { "uri": "https://..." }7  },8  "created_at": "2024-01-15T10:30:00Z"9}

Errors

These apply to both POST /run and POST /apps/run (same handler).

StatusCodeDescription
404not_foundApp ref does not exist
404SESSION_NOT_FOUNDSession ID does not exist (when reusing session)
403forbiddenNo permission to run the app
403blocked_by_usage_policyThe app (or its publisher) is outside your workspace usage policy. Checked before balance — a blocked app returns this even when credits are zero, not payment_required.
402payment_requiredInsufficient balance for a run the usage policy already allows, or the workspace's spending is locked, on hold, or suspended (free runs included)
402payment_method_requiredA run certain to cost $0 when the balance would refuse it and the workspace has no saved payment method. meta.billing_page names the page that adds one. See Billing: free runs
409APP_MISMATCHSession is bound to a different app
409VERSION_MISMATCHSession is bound to a different app version
410SESSION_EXPIREDSession timed out (when reusing an existing session ID)
410SESSION_ENDEDSession was explicitly ended
410app_retiredApp has been retired — error.message includes the app's status_message
412precondition_failedMissing setup requirements — see Credentials
422validation_errorInvalid input — for example an unknown function on a multi-function app. The data array lists field errors; unknown-function errors include available function names in the message.
503app_maintenanceApp is temporarily unavailable — error.message includes the app's status_message; response includes Retry-After: 3600

When the app ref is wrong, the response is not_found without suggestions; use Search or Store apps to discover apps.


Get Task

GET /tasks/:id

Get task status and output.

Response

Same as Run Task response.

Example:

bash
1curl https://api.inference.sh/tasks/task_abc123 \2  -H "Authorization: Bearer inf_your_key"

List Tasks

POST /tasks/list

List your tasks with cursor-based pagination. Requires the apps:read scope.

Request

FieldTypeDescription
limitnumberMax results per page (default 10)
cursorstringPagination cursor from a previous response
directionstring"next" or "prev" (default "next")
filtersarrayFilter objects (field, operator, value)
sortarraySort objects (field, dir)

Filter by status — use an integer code or a status name from Task status codes (received, queued, dispatched, preparing, serving, setting_up, running, cancelling, uploading, completed, failed, cancelled, rejected):

json
1{2  "limit": 20,3  "filters": [4    { "field": "status", "operator": "eq", "value": 10 }5  ]6}

String names are accepted and converted server-side (for example "completed" is equivalent to 10):

json
1{2  "limit": 20,3  "filters": [4    { "field": "status", "operator": "eq", "value": "completed" }5  ]6}

For in / not_in operators, each array element may be an integer or a recognized status name. Unrecognized status strings return 400 with code invalid_filter.

Filter by app:

json
1{2  "limit": 20,3  "filters": [4    { "field": "app_id", "operator": "eq", "value": "app_xyz789" }5  ]6}

Response

FieldTypeDescription
itemsarrayTask objects (same shape as Get Task)
next_cursorstringCursor for the next page
prev_cursorstringCursor for the previous page
has_nextbooleanMore results available
has_previousbooleanPrevious page available
total_itemsnumberTotal matching tasks

Example:

bash
1curl -X POST https://api.inference.sh/tasks/list \2  -H "Authorization: Bearer inf_your_key" \3  -H "Content-Type: application/json" \4  -d '{"limit": 10}'

From the CLI: belt task list (alias belt task ls). See CLI setup.


Queue stats

GET /tasks/queue-stats

Returns queue depth for your workspace: how many tasks are waiting for workers, scheduled for later, or actively running. Requires the apps:read scope. Counts are scoped to tasks you can see (same visibility rules as List Tasks).

Use this to monitor backlog before scaling workers or alerting on capacity. See also Queued longer than expected?.

Response

FieldTypeDescription
total_queuednumberTasks in Queued status
with_run_atnumberQueued tasks with run_at in the future (scheduled)
ready_to_runnumberQueued tasks ready to dispatch now
in_progressnumberTasks in active execution statuses (dispatched through uploading)
by_apparrayBreakdown by app
by_app_functionarrayBreakdown by app, version, and function

Each breakdown entry:

FieldTypeDescription
app_idstringApp ID
app_namestringnamespace/name when available
version_idstringApp version ID
functionstringFunction name (when set)
countnumberQueued tasks in this group
with_run_atnumberSubset with future run_at
in_progressnumberSubset actively running

Example:

bash
1curl https://api.inference.sh/tasks/queue-stats \2  -H "Authorization: Bearer inf_your_key"
json
1{2  "total_queued": 12,3  "with_run_at": 2,4  "ready_to_run": 10,5  "in_progress": 4,6  "by_app": [7    {8      "app_id": "app_xyz789",9      "app_name": "myteam/image-gen",10      "count": 8,11      "with_run_at": 0,12      "in_progress": 313    }14  ],15  "by_app_function": []16}

Get Task Status

GET /tasks/:id/status

Lightweight status poll without fetching full task input, output, or logs. Useful when you only need to know whether a task is still running.

Response

FieldTypeDescription
idstringTask ID
statusnumberStatus code
updated_atstringISO timestamp of last update

Example:

bash
1curl https://api.inference.sh/tasks/task_abc123/status \2  -H "Authorization: Bearer inf_your_key"

Get Task Logs

GET /tasks/:id/logs

Returns execution logs and status events for a task without the full task payload.

Response

FieldTypeDescription
task_idstringTask ID
statusnumberCurrent status code
eventsarrayStatus transition events
logsarrayLog entries (log_type, content)

Log types

log_typeNameTypical content
0buildContainer image build output
1runApp runtime stdout/stderr
2serveModel serving logs
3setupSetup-phase initialization
4taskTask-level messages

Example:

bash
1curl https://api.inference.sh/tasks/task_abc123/logs \2  -H "Authorization: Bearer inf_your_key"

From the CLI: belt task get <id> -f streams status until complete; belt task logs <id> -f tails live logs (filter with --type setup). See CLI setup.

JavaScript SDK: client.tasks.getLogs('task_abc123')


Get Task Timings

GET /tasks/:id/timings

Returns a timing breakdown derived from status events — total duration, phase groups, and per-transition timings.

Response

FieldTypeDescription
task_idstringTask ID
statusnumberCurrent status code
total_durationstringHuman-readable total duration
total_duration_msnumberTotal duration in milliseconds
groupsarrayHigh-level phases (label, start_at, end_at, duration, duration_ms)
eventsarrayPer-status transitions with durations

Example:

bash
1curl https://api.inference.sh/tasks/task_abc123/timings \2  -H "Authorization: Bearer inf_your_key"

From the CLI: belt task timings <id>. See CLI setup.

JavaScript SDK: client.tasks.getTimings('task_abc123')


Get Task Telemetry

GET /tasks/:id/telemetry

Returns time-series resource samples collected while the task ran on a worker (CPU, RAM, GPU, and volume usage). Samples are recorded by the engine during execution and stored in TimescaleDB.

Requires the same access as Get Task (apps:read scope). Long runs may return up to 100 downsampled points so responses stay bounded.

Response

Array of telemetry records under data:

FieldTypeDescription
idstringSample record ID
timestampstringISO timestamp when the sample was taken
task_idstringTask ID
task_seqnumberMonotonic sequence within the task
app_idstringApp that ran
app_version_idstringApp version
engine_idstringEngine that hosted the worker
worker_idstringWorker that executed the task
system_infoobjectWorker CPU, RAM, GPU, and volume metrics at this sample
engine_resourcesobjectEngine-level CPU, RAM, GPU, and volume metrics at this sample

Each system_info / engine_resources object includes:

Nested fieldDescription
cpusPer-CPU usage (usage, normalized_usage, core metadata)
ramMemory totals and usage percentages
gpusGPU memory, temperature, and driver metadata (when present)
volumesDisk volume size and usage

Example:

bash
1curl https://api.inference.sh/tasks/task_abc123/telemetry \2  -H "Authorization: Bearer inf_your_key"

JavaScript SDK:

typescript
1const { data: samples } = await client.tasks.getTelemetry('task_abc123');

Telemetry is most useful for debugging resource-heavy apps (large models, GPU runs, or disk-heavy pipelines). For phase durations without resource metrics, use Get Task Timings.

→ Observability · SDK overview — inspect and observability


Cancel Task

POST /tasks/:id/cancel

Cancel a running task. By default the platform requests a graceful stop (apps with an on_cancel hook can clean up first).

Request body (optional)

FieldTypeDescription
forcebooleanIf true, skip the graceful stop and end the run immediately
timeoutnumberMilliseconds the app gets to stop on its own before the run is ended for it (default 10000)

Either way the worker is free for the next task when the call returns. An app that stops on its own keeps its loaded state; one that is ended for it is restarted, so the next task on that worker runs setup() again. See Graceful cancellation.

Example (graceful):

bash
1curl -X POST https://api.inference.sh/tasks/task_abc123/cancel \2  -H "Authorization: Bearer inf_your_key"

Example (force kill):

bash
1curl -X POST https://api.inference.sh/tasks/task_abc123/cancel \2  -H "Authorization: Bearer inf_your_key" \3  -H "Content-Type: application/json" \4  -d '{"force": true}'

Response

json
1{2  "id": "task_abc123",3  "status": 12,4  "cancelled": true5}

Delete Task

DELETE /tasks/:id

Delete a finished task. Requires the apps:execute scope.

A task that is still queued or running answers 409 conflict. Cancel it first, or wait for it to finish.

Query parameters

ParameterTypeDescription
filesbooleanIf true, also delete the task's input and output files. Default false: the files stay in your workspace

With files=true the files are deleted even when another task, flow or chat still uses them. Their URLs stop resolving. Files you cannot delete are skipped, as in Delete Task Files; they do not stop the task from being deleted.

Example (task only):

bash
1curl -X DELETE https://api.inference.sh/tasks/task_abc123 \2  -H "Authorization: Bearer inf_your_key"

Example (task and its files):

bash
1curl -X DELETE "https://api.inference.sh/tasks/task_abc123?files=true" \2  -H "Authorization: Bearer inf_your_key"

CLI equivalent: belt task delete <task-id> (add --files to delete its files too, --yes to skip the confirmation prompt).


Attach Task Files

POST /tasks/:id/files

Create platform file records for a task and link them to it as output files. Requires the apps:execute scope and write access to the task.

Workers call this while a task runs to register uploads; the caller then PUTs the bytes to each upload_url, as with Upload File. Files attached here appear in List Task Files even when the task's output never names their URLs.

The body is the same as POST /files: a files array of partial file descriptors.

bash
1curl -X POST https://api.inference.sh/tasks/task_abc123/files \2  -H "Authorization: Bearer inf_your_key" \3  -H "Content-Type: application/json" \4  -d '{"files":[{"uri":"","filename":"image.png","content_type":"image/png","size":102400}]}'

Response: FileDTO[], the same shape as Upload File.

StatusDescription
400Invalid JSON body
403No write access to the task
500Any other failure, including a task that does not exist

There is no SDK helper for this endpoint.


List Task Files

GET /tasks/:id/files

List the files a task consumed and produced. Requires the apps:read scope.

Use this to get the file IDs behind the URLs in a task's input and output, for example to delete one file with DELETE /files/:id.

Files are found from the platform URLs in the task's input and output and from the files linked to the task, including uploads attached with POST /tasks/:id/files that output never names. Files you cannot read (for example another workspace's file named in an input by its public URL) are left out.

Query parameters

ParameterTypeDescription
rolestringinput or output to list one side only. Omit for both. Any other value answers 400 validation_error

Response

json
1[2  {3    "id": "8k2m4n6p8q0r2s4t6v8w0x2y4z",4    "created_at": "2026-10-07T08:31:12Z",5    "role": "input",6    "uri": "https://cloud.inference.sh/t/1a2b3c4d/5e6f7g8h.png",7    "filename": "photo.png",8    "content_type": "image/png",9    "size": 10240010  },11  {12    "id": "9l3n5p7q9r1s3t5v7w9x1y3z5a",13    "created_at": "2026-10-07T08:31:15Z",14    "role": "output",15    "uri": "https://cloud.inference.sh/t/1a2b3c4d/9i0j1k2l.png",16    "filename": "result.png",17    "content_type": "image/png",18    "size": 24576019  }20]
FieldDescription
idFile ID, as DELETE /files/:id takes it
roleinput if the task consumed the file, output if it produced it. A file the app passes through from input to output is an input
uriThe URL that appears in the task's input or output

Only files stored on inference.sh are listed. An input you passed as a URL on your own storage is not a file here and does not appear.

CLI equivalent: belt task files <task-id> (add --role input or --role output, --json for the raw payload).


Delete Task Files

DELETE /tasks/:id/files

Delete a finished task's files and keep the task. Requires the apps:execute scope.

The task record stays, with its input and output unchanged; the file URLs in them stop resolving. A task that is still queued or running answers 409 conflict.

A file is deleted even when another task, flow or chat still uses it. If you reuse one uploaded input across several tasks, pass role=output to keep it.

Query parameters

ParameterTypeDescription
rolestringinput or output to delete one side only. Omit for both. Any other value answers 400 validation_error

Example:

bash
1curl -X DELETE https://api.inference.sh/tasks/task_abc123/files \2  -H "Authorization: Bearer inf_your_key"

Response

json
1{2  "deleted": ["8k2m4n6p8q0r2s4t6v8w0x2y4z", "9l3n5p7q9r1s3t5v7w9x1y3z5a"],3  "skipped": []4}
FieldDescription
deletedIDs of the files that were deleted
skippedFiles left in place, each with an id and a reason: forbidden (the file belongs to another workspace) or failed (the delete did not go through; call again to retry)

The call is safe to repeat: files already deleted are not listed again.

CLI equivalent: belt task delete-files <task-id> (add --role output to keep the inputs, --yes to skip the confirmation prompt).


Infrastructure routing

The infra field controls which workers the scheduler considers:

ValueBehavior
cloudCloud workers only (default when infra is omitted on POST /run)
privateYour workspace's private workers only
private_firstTry private workers first; fall back to cloud if none are available

private_first is useful when you prefer your own hardware but still want runs to succeed when private capacity is offline or busy. The scheduler ranks private workers ahead of cloud workers for matching tasks.

Apps may restrict which infra types they allow (for example cloud-only store apps). If the chosen infra is not permitted, the task fails immediately. If no worker is available yet, the task stays Queued until capacity appears or the queue expires.

→ Workers · Using private workers


Stream Task Updates

GET /tasks/:id/stream

Receive task status, logs, and output over Server-Sent Events (SSE) instead of polling GET /tasks/:id.

→ Streaming API

Use polling (GET /tasks/:id in a loop) when your environment cannot hold long-lived connections. The Python and JavaScript SDKs also support stream: false — see SDK polling.


Get Task Cost

GET /usage/tasks/:id/cost

Get the cost breakdown for a completed task.

Response

FieldTypeDescription
totalnumberTotal cost in microcents (1 microcent = $0.00000001)
discountnumberTotal discount applied in microcents (omitted if zero)
chargednumberAmount actually charged in microcents
refundednumberAmount refunded in microcents (omitted if zero)

Example:

bash
1curl https://api.inference.sh/usage/tasks/task_abc123/cost \2  -H "Authorization: Bearer inf_your_key"

Response:

json
1{2  "total": 50000,3  "charged": 500004}

See REST overview — response format.

Note: All values are in microcents. To convert to dollars: dollars = microcents / 100000000. For example, 50000 microcents = $0.0005.

Errors

StatusCodeDescription
403forbiddenYou don't have permission to access this task
404not_foundCost not found for this task

Task Status Codes

StatusCodeDescription
Received1Task received
Queued2Waiting for worker
Dispatched3Assigned to worker
Preparing4Setting up environment
Serving5Loading model
Setting Up6Task initialization
Running7Executing
Cancelling8Cancel requested; worker shutting down
Uploading9Uploading results
Completed10Done
Failed11Error occurred
Cancelled12Cancelled
Rejected13Refused before running: the workspace has no balance or no payment method. The input is kept; the run can be retried.

Task failure messages

When status is 11 (Failed), the error string describes the failure. App errors pass through from your code unchanged. Platform failures return short, retry-friendly messages without internal scheduler or worker details.

error valueMeaning
task interrupted, please retryTransient infrastructure issue (worker disconnect, engine reconnect, orphaned task)
task could not be dispatched, please retryCould not assign a worker when the task was submitted
task could not be processed after multiple attempts, please retryExceeded dispatch retry limit while stuck in Dispatched
task expired while waiting for available capacity, please retryQueued ~24 hours with no available worker
no active workers with matching resourcesNo worker matches GPU/VRAM/infra (~10 minutes)
no available workers — capacity reserved for higher-priority appsMatching cloud workers exist but are reserved by another app's min_concurrency floor (~10 minutes)
failed to prepare secrets for this app, please check your secret configurationMissing or invalid workspace secret
session worker busy too longSession worker busy for ~30 seconds
session worker offlineSession's worker is no longer available
session expired or not foundInvalid session ID or idle timeout

→ Failed tasks and error messages · Troubleshooting


cURL Examples

Run and wait

bash
1curl -X POST https://api.inference.sh/run \2  -H "Authorization: Bearer inf_your_key" \3  -H "Content-Type: application/json" \4  -d '{5    "app": "infsh/flux",6    "input": {"prompt": "A sunset"}7  }'

Run without waiting

bash
1curl -X POST "https://api.inference.sh/run?wait=false" \2  -H "Authorization: Bearer inf_your_key" \3  -H "Content-Type: application/json" \4  -d '{5    "app": "infsh/flux",6    "input": {"prompt": "A sunset"}7  }'

Run with session

bash
1# Start a new session2curl -X POST https://api.inference.sh/run \3  -H "Authorization: Bearer inf_your_key" \4  -H "Content-Type: application/json" \5  -d '{6    "app": "my-app",7    "input": {"action": "init"},8    "session": "new"9  }'10# Response includes session_id: "sess_abc123"1112# Continue session13curl -X POST https://api.inference.sh/run \14  -H "Authorization: Bearer inf_your_key" \15  -H "Content-Type: application/json" \16  -d '{17    "app": "my-app",18    "input": {"action": "process"},19    "session": "sess_abc123"20  }'

Run with custom session timeout

bash
1# Start session with 5-minute idle timeout2curl -X POST https://api.inference.sh/run \3  -H "Authorization: Bearer inf_your_key" \4  -H "Content-Type: application/json" \5  -d '{6    "app": "my-app",7    "input": {"action": "init"},8    "session": "new",9    "session_timeout": 30010  }'

See Sessions Developer Guide for full documentation.

Session errors on run

When you pass an existing session ID to POST /run or POST /apps/run and the session has timed out, the API returns 410 Gone with code SESSION_EXPIRED. Start a new session with "session": "new".

Other session errors on run (SESSION_NOT_FOUND, SESSION_ENDED, APP_MISMATCH, VERSION_MISMATCH) are listed in Run Task errors above. WORKER_LEASED and other session-management errors are documented on the Sessions API. See also Sessions developer guide — Error handling.


Webhooks

Get notified when a task completes by providing a webhook URL. When the task reaches a terminal state, a POST request is sent to your URL.

Run with webhook

bash
1curl -X POST https://api.inference.sh/run \2  -H "Authorization: Bearer inf_your_key" \3  -H "Content-Type: application/json" \4  -d '{5    "app": "infsh/flux",6    "input": {"prompt": "A sunset"},7    "webhook": "https://your-server.com/webhook"8  }'

Webhook payload

Your endpoint receives a JSON POST with the task result:

json
1{2  "event": "task.completed",3  "timestamp": "2024-01-15T10:30:05Z",4  "data": {5    "id": "task_abc123",6    "short_id": "abc123",7    "status": 10,8    "status_text": "completed",9    "output": { "image": { "uri": "https://..." } },10    "created_at": "2024-01-15T10:30:00Z",11    "updated_at": "2024-01-15T10:30:05Z"12  }13}
FieldTypeDescription
eventstringtask.completed, task.failed, or task.cancelled
timestampstringWhen the webhook was sent (ISO 8601, UTC)
dataobjectThe task result, fields below

data fields:

FieldTypeDescription
idstringTask ID
short_idstringShort task ID
statusnumberTerminal status code (10=completed, 11=failed, 12=cancelled)
status_textstringStatus name (completed, failed, cancelled)
outputobjectTask output (when completed; null when there is none)
errorstringError message. Present only when the task has one
session_idstringSession ID. Present only when the task ran in a session
created_atstringISO timestamp
updated_atstringISO timestamp
run_atstringScheduled start time (UTC). Present only for scheduled tasks

The webhook is sent when the task reaches a terminal status. Delivery is not retried: a failed request or a 4xx/5xx response is logged and dropped. The request times out after 10 seconds, and only public addresses are called.

we use cookies

we use cookies to ensure you get the best experience on our website. for more information on how we use cookies, please see our cookie policy.

by clicking "accept", you agree to our use of cookies.
learn more.