---
title: Tasks | Runware Docs
url: https://runware.ai/docs/serverless/api-tasks
description: Invoke an endpoint synchronously or asynchronously, then read the task back.
relatedDocuments:
  - https://runware.ai/docs/serverless/api
  - https://runware.ai/docs/serverless/invoking
  - https://runware.ai/docs/serverless/errors
---
## Introduction

Two routes start a task and **they differ only in how the wait happens, not in whether you get a result**. The synchronous route holds the connection open and answers with the finished task, or with `202` when the platform's wait window expires first. The asynchronous route accepts and returns immediately.

Both take the same body: a `taskId` you generate and a `payload` shaped by the endpoint you are calling. **Sending the same id again returns the task it already names** rather than starting a second run, which is what makes a retry after a lost response safe.

> [!NOTE]
> A `202` is not a failure. Poll the task with `getTask` under the `appId` the response names. See [Invoking an app](https://runware.ai/docs/serverless/invoking).

## Start a sync task

POSTapi.serverless.runware.ai/v1/apps/{appId}/invoke-sync/{endpointPath}

Starts a new sync task on `appId`, routing the request body payload to an available worker. The request blocks until the task is terminal and returns the result inline (`200`). Resubmitting a task id waits on the task it already names rather than starting a second one, so the `200` carries that task's result and may name a different `appId`. Poll it under the one returned. A task that outlives the wait window is **not** a failure: the task is still queued or running, and the response is `202` carrying that task with `status: pending`, the same shape `invoke-async` returns, and it names the owning `appId` on a resubmission just as the `200` does. Poll `GET /v1/apps/{appId}/tasks/{taskId}` for its result. A request the platform cannot attribute to an accepted task fails instead, with no task to poll. Apps in `initializing`, `active`, or `stopping` accept invocation, with two exceptions: an `initializing` app whose first rollout has not produced a version returns `409 Conflict`, and an `active` app the platform has observed to have no workload able to serve returns `503 Service Unavailable` with no task minted, typed `capacity-unavailable` and carrying `Retry-After`. `stopped`, `deleting`, and `failed` return `409 Conflict`. Unknown or deleted apps return `404 Not Found`. An organization whose serverless tenancy is revoked, or has no tenancy receipt at all, returns `403 Forbidden`, distinguishing that from an app that does not exist. An organization whose tenancy is still being provisioned returns `503 Service Unavailable` instead. That state is retryable, not a revocation, and clears once provisioning finishes. Endpoint membership is checked against the active version's endpoint set before the task is accepted: an endpoint the app does not declare returns `404` whose `endpointPath` extension member carries the rejected path, distinguishing it from an unknown app, and the task never enters the queue.

### [Request](#start-sync-task-request)

Path

### [appId](#start-sync-task-path-appid)

- **Type**: `string`
- **Required**: true
- **Min**: `6`
- **Max**: `30`

Immutable app identifier, unique among the authenticated organization's live apps.

### [endpointPath](#start-sync-task-path-endpointpath)

- **Type**: `string`
- **Required**: true
- **Min**: `1`
- **Max**: `255`

Path of the endpoint to route the task to, as returned by `listEndpoints`: one or more bare lowercase segments joined by slashes, such as `generate` or `v1/chat/completions`, with no leading or trailing slash. Send those slashes unencoded. A generated client that escapes `/` as `%2F` is rejected with `422`.

Body

### [taskId](#start-sync-task-body-taskid)

- **Type**: `string (uuid)`
- **Required**: true
- **Format**: `UUID v4`
- **Min**: `36`
- **Max**: `36`

Client-generated task identifier, canonical lowercase UUID. One id is one task: resubmitting it is answered with the task it already names rather than starting a second, so a request whose response was lost can be sent again without paying for the work twice. Reusing an id for a different request returns the first task, so the id is the caller's to keep unique.

### [payload](#start-sync-task-body-payload)

- **Type**: `object`
- **Required**: true

The body the endpoint's handler receives, validated against the endpoint's declared input schema. An endpoint that declares none takes it unvalidated.

### [Response](#start-sync-task-response)

### [id](#start-sync-task-response-id)

- **Type**: `string`
- **Required**: true

Task identifier, supplied by the caller when the task was submitted.

### [status](#start-sync-task-response-status)

- **Type**: `string`
- **Required**: true

**Possible values**: `pending` `completed` `failed`

### [appId](#start-sync-task-response-appid)

- **Type**: `string`
- **Required**: true
- **Min**: `6`
- **Max**: `30`

Immutable app identifier. Unique among the authenticated organization's live apps: it cannot be changed after creation, and it becomes available again once the app it named reaches `deleted`.

### [endpointPath](#start-sync-task-response-endpointpath)

- **Type**: `string`
- **Required**: true
- **Min**: `1`
- **Max**: `255`

Path of the endpoint to route the task to: one or more bare lowercase segments joined by slashes, such as `generate` or `v1/chat/completions`, with no leading or trailing slash. Send those slashes unencoded. A generated client that escapes `/` as `%2F` is rejected with `422`.

### [output](#start-sync-task-response-output)

- **Type**: `any`

Inference result payload on success. Null otherwise. May be any JSON value, including an object, array, string, number, boolean, or null.

### [error](#start-sync-task-response-error)

- **Type**: `string (nullable)`

Unstructured error message when `status` is `failed`. Null otherwise. It reports a task the platform accepted and that then failed. Its wording is not part of this contract: it carries no stable code or retry signal, so do not parse it to classify a failure.

### [createdAt](#start-sync-task-response-createdat)

- **Type**: `string (date-time)`
- **Required**: true
- **Format**: `date-time`

### [completedAt](#start-sync-task-response-completedat)

- **Type**: `string (date-time) (nullable)`
- **Format**: `date-time`

### [Errors](#start-sync-task-errors)

<table><tbody><tr><td data-rw-cid-pz7tphoj="true">Status</td><td data-rw-cid-pz7tphoj="true">When</td></tr><tr><td data-rw-cid-pz7tphoj="true"><code data-rw-cid-pz7tphoj="">400</code></td><td data-rw-cid-pz7tphoj="true">The request was malformed and could not be parsed (e.g. invalid JSON). A well-formed request that fails validation returns <code class="component-Code">422</code> instead.</td></tr><tr><td data-rw-cid-pz7tphoj="true"><code data-rw-cid-pz7tphoj="">401</code></td><td data-rw-cid-pz7tphoj="true">Missing or invalid credentials</td></tr><tr><td data-rw-cid-pz7tphoj="true"><code data-rw-cid-pz7tphoj="">403</code></td><td data-rw-cid-pz7tphoj="true">Authenticated but not permitted to access this resource</td></tr><tr><td data-rw-cid-pz7tphoj="true"><code data-rw-cid-pz7tphoj="">404</code></td><td data-rw-cid-pz7tphoj="true">The app does not exist, or it exists and does not declare the endpoint path. An undeclared endpoint carries <code class="component-Code">endpointPath</code> with the rejected path. Its absence means the app itself was not found.</td></tr><tr><td data-rw-cid-pz7tphoj="true"><code data-rw-cid-pz7tphoj="">409</code></td><td data-rw-cid-pz7tphoj="true">Resource already exists or the request conflicts with its current state</td></tr><tr><td data-rw-cid-pz7tphoj="true"><code data-rw-cid-pz7tphoj="">413</code></td><td data-rw-cid-pz7tphoj="true">The request body exceeds its size limit: 10 MiB on <code class="component-Code">invoke-sync</code> and <code class="component-Code">invoke-async</code>, whose body carries the endpoint's payload, and 1 MiB on the other operations that answer with this response. <code class="component-Code">detail</code> names the limit in bytes.</td></tr><tr><td data-rw-cid-pz7tphoj="true"><code data-rw-cid-pz7tphoj="">415</code></td><td data-rw-cid-pz7tphoj="true">The request body arrived with a Content-Type this operation does not accept. The body was not decoded, so this is not a schema failure. A body of <code class="component-Code">application/json</code> that cannot be parsed returns <code class="component-Code">400</code>. One that parses and breaks the schema returns <code class="component-Code">422</code>. A body sent with no Content-Type is the same refusal.</td></tr><tr><td data-rw-cid-pz7tphoj="true"><code data-rw-cid-pz7tphoj="">422</code></td><td data-rw-cid-pz7tphoj="true">The request was well-formed but semantically invalid (e.g. a missing or out-of-range field). A request that could not be parsed returns <code class="component-Code">400</code>. The <code class="component-Code">errors</code> array carries one entry per offending field.</td></tr><tr><td data-rw-cid-pz7tphoj="true"><code data-rw-cid-pz7tphoj="">500</code></td><td data-rw-cid-pz7tphoj="true">Unexpected server error</td></tr><tr><td data-rw-cid-pz7tphoj="true"><code data-rw-cid-pz7tphoj="">503</code></td><td data-rw-cid-pz7tphoj="true">The invocation could not be accepted and no task was minted. The problem <code class="component-Code">type</code> says which of two conditions applies, because the client's next move differs. <code class="component-Code">capacity-unavailable</code> means the app is deployed and correct, and the platform has no workload able to serve it: the app is short of the workers it asks for, or it has work waiting and nothing running it. The request is unchanged by the refusal and succeeds as sent once capacity returns, so retry it rather than correct it, after <code class="component-Code">Retry-After</code> where that header is present. Read <code class="component-Code">health.reason</code> on the app to tell the two capacity conditions apart. <code class="component-Code">service-unavailable</code> means something this route depends on is temporarily unreachable, or the organization's serverless tenancy is still being provisioned. That is retryable too, but it says nothing about the app.</td></tr></tbody></table>

## Start an async task

POSTapi.serverless.runware.ai/v1/apps/{appId}/invoke-async/{endpointPath}

Starts a new async task on `appId`, routing the request body payload to an available worker. The task runs asynchronously and the response is `202`. Poll `GET /v1/apps/{appId}/tasks/{taskId}` for completion. Resubmitting a task id is answered with the task it already names rather than starting a second one, so the `202` can carry a task that has already finished: read its `status` instead of assuming `pending`, and note it may name a different `appId`. Apps in `initializing`, `active`, or `stopping` accept invocation, with two exceptions: an `initializing` app whose first rollout has not produced a version returns `409 Conflict`, and an `active` app the platform has observed to have no workload able to serve returns `503 Service Unavailable` with no task minted, typed `capacity-unavailable` and carrying `Retry-After`. `stopped`, `deleting`, and `failed` return `409 Conflict`. Unknown or deleted apps return `404 Not Found`. An organization whose serverless tenancy is revoked, or has no tenancy receipt at all, returns `403 Forbidden`, distinguishing that from an app that does not exist. An organization whose tenancy is still being provisioned returns `503 Service Unavailable` instead. That state is retryable, not a revocation, and clears once provisioning finishes. Endpoint membership is checked against the active version's endpoint set before the task is accepted: an endpoint the app does not declare returns `404` whose `endpointPath` extension member carries the rejected path, distinguishing it from an unknown app, and the task never enters the queue.

### [Request](#start-async-task-request)

Path

### [appId](#start-async-task-path-appid)

- **Type**: `string`
- **Required**: true
- **Min**: `6`
- **Max**: `30`

Immutable app identifier, unique among the authenticated organization's live apps.

### [endpointPath](#start-async-task-path-endpointpath)

- **Type**: `string`
- **Required**: true
- **Min**: `1`
- **Max**: `255`

Path of the endpoint to route the task to, as returned by `listEndpoints`: one or more bare lowercase segments joined by slashes, such as `generate` or `v1/chat/completions`, with no leading or trailing slash. Send those slashes unencoded. A generated client that escapes `/` as `%2F` is rejected with `422`.

Body

### [taskId](#start-async-task-body-taskid)

- **Type**: `string (uuid)`
- **Required**: true
- **Format**: `UUID v4`
- **Min**: `36`
- **Max**: `36`

Client-generated task identifier, canonical lowercase UUID. One id is one task: resubmitting it is answered with the task it already names rather than starting a second, so a request whose response was lost can be sent again without paying for the work twice. Reusing an id for a different request returns the first task, so the id is the caller's to keep unique.

### [payload](#start-async-task-body-payload)

- **Type**: `object`
- **Required**: true

The body the endpoint's handler receives, validated against the endpoint's declared input schema. An endpoint that declares none takes it unvalidated.

### [Response](#start-async-task-response)

### [id](#start-async-task-response-id)

- **Type**: `string`
- **Required**: true

Task identifier, supplied by the caller when the task was submitted.

### [status](#start-async-task-response-status)

- **Type**: `string`
- **Required**: true

**Possible values**: `pending` `completed` `failed`

### [appId](#start-async-task-response-appid)

- **Type**: `string`
- **Required**: true
- **Min**: `6`
- **Max**: `30`

Immutable app identifier. Unique among the authenticated organization's live apps: it cannot be changed after creation, and it becomes available again once the app it named reaches `deleted`.

### [endpointPath](#start-async-task-response-endpointpath)

- **Type**: `string`
- **Required**: true
- **Min**: `1`
- **Max**: `255`

Path of the endpoint to route the task to: one or more bare lowercase segments joined by slashes, such as `generate` or `v1/chat/completions`, with no leading or trailing slash. Send those slashes unencoded. A generated client that escapes `/` as `%2F` is rejected with `422`.

### [output](#start-async-task-response-output)

- **Type**: `any`

Inference result payload on success. Null otherwise. May be any JSON value, including an object, array, string, number, boolean, or null.

### [error](#start-async-task-response-error)

- **Type**: `string (nullable)`

Unstructured error message when `status` is `failed`. Null otherwise. It reports a task the platform accepted and that then failed. Its wording is not part of this contract: it carries no stable code or retry signal, so do not parse it to classify a failure.

### [createdAt](#start-async-task-response-createdat)

- **Type**: `string (date-time)`
- **Required**: true
- **Format**: `date-time`

### [completedAt](#start-async-task-response-completedat)

- **Type**: `string (date-time) (nullable)`
- **Format**: `date-time`

### [Errors](#start-async-task-errors)

<table><tbody><tr><td data-rw-cid-pz7tphoj="true">Status</td><td data-rw-cid-pz7tphoj="true">When</td></tr><tr><td data-rw-cid-pz7tphoj="true"><code data-rw-cid-pz7tphoj="">400</code></td><td data-rw-cid-pz7tphoj="true">The request was malformed and could not be parsed (e.g. invalid JSON). A well-formed request that fails validation returns <code class="component-Code">422</code> instead.</td></tr><tr><td data-rw-cid-pz7tphoj="true"><code data-rw-cid-pz7tphoj="">401</code></td><td data-rw-cid-pz7tphoj="true">Missing or invalid credentials</td></tr><tr><td data-rw-cid-pz7tphoj="true"><code data-rw-cid-pz7tphoj="">403</code></td><td data-rw-cid-pz7tphoj="true">Authenticated but not permitted to access this resource</td></tr><tr><td data-rw-cid-pz7tphoj="true"><code data-rw-cid-pz7tphoj="">404</code></td><td data-rw-cid-pz7tphoj="true">The app does not exist, or it exists and does not declare the endpoint path. An undeclared endpoint carries <code class="component-Code">endpointPath</code> with the rejected path. Its absence means the app itself was not found.</td></tr><tr><td data-rw-cid-pz7tphoj="true"><code data-rw-cid-pz7tphoj="">409</code></td><td data-rw-cid-pz7tphoj="true">Resource already exists or the request conflicts with its current state</td></tr><tr><td data-rw-cid-pz7tphoj="true"><code data-rw-cid-pz7tphoj="">413</code></td><td data-rw-cid-pz7tphoj="true">The request body exceeds its size limit: 10 MiB on <code class="component-Code">invoke-sync</code> and <code class="component-Code">invoke-async</code>, whose body carries the endpoint's payload, and 1 MiB on the other operations that answer with this response. <code class="component-Code">detail</code> names the limit in bytes.</td></tr><tr><td data-rw-cid-pz7tphoj="true"><code data-rw-cid-pz7tphoj="">415</code></td><td data-rw-cid-pz7tphoj="true">The request body arrived with a Content-Type this operation does not accept. The body was not decoded, so this is not a schema failure. A body of <code class="component-Code">application/json</code> that cannot be parsed returns <code class="component-Code">400</code>. One that parses and breaks the schema returns <code class="component-Code">422</code>. A body sent with no Content-Type is the same refusal.</td></tr><tr><td data-rw-cid-pz7tphoj="true"><code data-rw-cid-pz7tphoj="">422</code></td><td data-rw-cid-pz7tphoj="true">The request was well-formed but semantically invalid (e.g. a missing or out-of-range field). A request that could not be parsed returns <code class="component-Code">400</code>. The <code class="component-Code">errors</code> array carries one entry per offending field.</td></tr><tr><td data-rw-cid-pz7tphoj="true"><code data-rw-cid-pz7tphoj="">500</code></td><td data-rw-cid-pz7tphoj="true">Unexpected server error</td></tr><tr><td data-rw-cid-pz7tphoj="true"><code data-rw-cid-pz7tphoj="">503</code></td><td data-rw-cid-pz7tphoj="true">The invocation could not be accepted and no task was minted. The problem <code class="component-Code">type</code> says which of two conditions applies, because the client's next move differs. <code class="component-Code">capacity-unavailable</code> means the app is deployed and correct, and the platform has no workload able to serve it: the app is short of the workers it asks for, or it has work waiting and nothing running it. The request is unchanged by the refusal and succeeds as sent once capacity returns, so retry it rather than correct it, after <code class="component-Code">Retry-After</code> where that header is present. Read <code class="component-Code">health.reason</code> on the app to tell the two capacity conditions apart. <code class="component-Code">service-unavailable</code> means something this route depends on is temporarily unreachable, or the organization's serverless tenancy is still being provisioned. That is retryable too, but it says nothing about the app.</td></tr></tbody></table>

## Start a sync task on the default endpoint

POSTapi.serverless.runware.ai/v1/apps/{appId}/invoke-sync

Starts a new sync task on `appId`, routing the request body payload to the endpoint the app marks as its default. The request body, responses, and task semantics match `POST /v1/apps/{appId}/invoke-sync/{endpointPath}`. An app that marks no default endpoint returns `404` with no `endpointPath` member and a detail naming the requirement. An unknown or deleted app returns the same status with a detail that does not name a missing default.

### [Request](#start-default-sync-task-request)

Path

### [appId](#start-default-sync-task-path-appid)

- **Type**: `string`
- **Required**: true
- **Min**: `6`
- **Max**: `30`

Immutable app identifier, unique among the authenticated organization's live apps.

Body

### [taskId](#start-default-sync-task-body-taskid)

- **Type**: `string (uuid)`
- **Required**: true
- **Format**: `UUID v4`
- **Min**: `36`
- **Max**: `36`

Client-generated task identifier, canonical lowercase UUID. One id is one task: resubmitting it is answered with the task it already names rather than starting a second, so a request whose response was lost can be sent again without paying for the work twice. Reusing an id for a different request returns the first task, so the id is the caller's to keep unique.

### [payload](#start-default-sync-task-body-payload)

- **Type**: `object`
- **Required**: true

The body the endpoint's handler receives, validated against the endpoint's declared input schema. An endpoint that declares none takes it unvalidated.

### [Response](#start-default-sync-task-response)

### [id](#start-default-sync-task-response-id)

- **Type**: `string`
- **Required**: true

Task identifier, supplied by the caller when the task was submitted.

### [status](#start-default-sync-task-response-status)

- **Type**: `string`
- **Required**: true

**Possible values**: `pending` `completed` `failed`

### [appId](#start-default-sync-task-response-appid)

- **Type**: `string`
- **Required**: true
- **Min**: `6`
- **Max**: `30`

Immutable app identifier. Unique among the authenticated organization's live apps: it cannot be changed after creation, and it becomes available again once the app it named reaches `deleted`.

### [endpointPath](#start-default-sync-task-response-endpointpath)

- **Type**: `string`
- **Required**: true
- **Min**: `1`
- **Max**: `255`

Path of the endpoint to route the task to: one or more bare lowercase segments joined by slashes, such as `generate` or `v1/chat/completions`, with no leading or trailing slash. Send those slashes unencoded. A generated client that escapes `/` as `%2F` is rejected with `422`.

### [output](#start-default-sync-task-response-output)

- **Type**: `any`

Inference result payload on success. Null otherwise. May be any JSON value, including an object, array, string, number, boolean, or null.

### [error](#start-default-sync-task-response-error)

- **Type**: `string (nullable)`

Unstructured error message when `status` is `failed`. Null otherwise. It reports a task the platform accepted and that then failed. Its wording is not part of this contract: it carries no stable code or retry signal, so do not parse it to classify a failure.

### [createdAt](#start-default-sync-task-response-createdat)

- **Type**: `string (date-time)`
- **Required**: true
- **Format**: `date-time`

### [completedAt](#start-default-sync-task-response-completedat)

- **Type**: `string (date-time) (nullable)`
- **Format**: `date-time`

### [Errors](#start-default-sync-task-errors)

<table><tbody><tr><td data-rw-cid-pz7tphoj="true">Status</td><td data-rw-cid-pz7tphoj="true">When</td></tr><tr><td data-rw-cid-pz7tphoj="true"><code data-rw-cid-pz7tphoj="">400</code></td><td data-rw-cid-pz7tphoj="true">The request was malformed and could not be parsed (e.g. invalid JSON). A well-formed request that fails validation returns <code class="component-Code">422</code> instead.</td></tr><tr><td data-rw-cid-pz7tphoj="true"><code data-rw-cid-pz7tphoj="">401</code></td><td data-rw-cid-pz7tphoj="true">Missing or invalid credentials</td></tr><tr><td data-rw-cid-pz7tphoj="true"><code data-rw-cid-pz7tphoj="">403</code></td><td data-rw-cid-pz7tphoj="true">Authenticated but not permitted to access this resource</td></tr><tr><td data-rw-cid-pz7tphoj="true"><code data-rw-cid-pz7tphoj="">404</code></td><td data-rw-cid-pz7tphoj="true">The app does not exist, or it exists and does not declare the endpoint path. An undeclared endpoint carries <code class="component-Code">endpointPath</code> with the rejected path. Its absence means the app itself was not found.</td></tr><tr><td data-rw-cid-pz7tphoj="true"><code data-rw-cid-pz7tphoj="">409</code></td><td data-rw-cid-pz7tphoj="true">Resource already exists or the request conflicts with its current state</td></tr><tr><td data-rw-cid-pz7tphoj="true"><code data-rw-cid-pz7tphoj="">413</code></td><td data-rw-cid-pz7tphoj="true">The request body exceeds its size limit: 10 MiB on <code class="component-Code">invoke-sync</code> and <code class="component-Code">invoke-async</code>, whose body carries the endpoint's payload, and 1 MiB on the other operations that answer with this response. <code class="component-Code">detail</code> names the limit in bytes.</td></tr><tr><td data-rw-cid-pz7tphoj="true"><code data-rw-cid-pz7tphoj="">415</code></td><td data-rw-cid-pz7tphoj="true">The request body arrived with a Content-Type this operation does not accept. The body was not decoded, so this is not a schema failure. A body of <code class="component-Code">application/json</code> that cannot be parsed returns <code class="component-Code">400</code>. One that parses and breaks the schema returns <code class="component-Code">422</code>. A body sent with no Content-Type is the same refusal.</td></tr><tr><td data-rw-cid-pz7tphoj="true"><code data-rw-cid-pz7tphoj="">422</code></td><td data-rw-cid-pz7tphoj="true">The request was well-formed but semantically invalid (e.g. a missing or out-of-range field). A request that could not be parsed returns <code class="component-Code">400</code>. The <code class="component-Code">errors</code> array carries one entry per offending field.</td></tr><tr><td data-rw-cid-pz7tphoj="true"><code data-rw-cid-pz7tphoj="">500</code></td><td data-rw-cid-pz7tphoj="true">Unexpected server error</td></tr><tr><td data-rw-cid-pz7tphoj="true"><code data-rw-cid-pz7tphoj="">503</code></td><td data-rw-cid-pz7tphoj="true">The invocation could not be accepted and no task was minted. The problem <code class="component-Code">type</code> says which of two conditions applies, because the client's next move differs. <code class="component-Code">capacity-unavailable</code> means the app is deployed and correct, and the platform has no workload able to serve it: the app is short of the workers it asks for, or it has work waiting and nothing running it. The request is unchanged by the refusal and succeeds as sent once capacity returns, so retry it rather than correct it, after <code class="component-Code">Retry-After</code> where that header is present. Read <code class="component-Code">health.reason</code> on the app to tell the two capacity conditions apart. <code class="component-Code">service-unavailable</code> means something this route depends on is temporarily unreachable, or the organization's serverless tenancy is still being provisioned. That is retryable too, but it says nothing about the app.</td></tr></tbody></table>

## Start an async task on the default endpoint

POSTapi.serverless.runware.ai/v1/apps/{appId}/invoke-async

Starts a new async task on `appId`, routing the request body payload to the endpoint the app marks as its default. The request body, responses, and task semantics match `POST /v1/apps/{appId}/invoke-async/{endpointPath}`. An app that marks no default endpoint returns `404` with no `endpointPath` member and a detail naming the requirement. An unknown or deleted app returns the same status with a detail that does not name a missing default.

### [Request](#start-default-async-task-request)

Path

### [appId](#start-default-async-task-path-appid)

- **Type**: `string`
- **Required**: true
- **Min**: `6`
- **Max**: `30`

Immutable app identifier, unique among the authenticated organization's live apps.

Body

### [taskId](#start-default-async-task-body-taskid)

- **Type**: `string (uuid)`
- **Required**: true
- **Format**: `UUID v4`
- **Min**: `36`
- **Max**: `36`

Client-generated task identifier, canonical lowercase UUID. One id is one task: resubmitting it is answered with the task it already names rather than starting a second, so a request whose response was lost can be sent again without paying for the work twice. Reusing an id for a different request returns the first task, so the id is the caller's to keep unique.

### [payload](#start-default-async-task-body-payload)

- **Type**: `object`
- **Required**: true

The body the endpoint's handler receives, validated against the endpoint's declared input schema. An endpoint that declares none takes it unvalidated.

### [Response](#start-default-async-task-response)

### [id](#start-default-async-task-response-id)

- **Type**: `string`
- **Required**: true

Task identifier, supplied by the caller when the task was submitted.

### [status](#start-default-async-task-response-status)

- **Type**: `string`
- **Required**: true

**Possible values**: `pending` `completed` `failed`

### [appId](#start-default-async-task-response-appid)

- **Type**: `string`
- **Required**: true
- **Min**: `6`
- **Max**: `30`

Immutable app identifier. Unique among the authenticated organization's live apps: it cannot be changed after creation, and it becomes available again once the app it named reaches `deleted`.

### [endpointPath](#start-default-async-task-response-endpointpath)

- **Type**: `string`
- **Required**: true
- **Min**: `1`
- **Max**: `255`

Path of the endpoint to route the task to: one or more bare lowercase segments joined by slashes, such as `generate` or `v1/chat/completions`, with no leading or trailing slash. Send those slashes unencoded. A generated client that escapes `/` as `%2F` is rejected with `422`.

### [output](#start-default-async-task-response-output)

- **Type**: `any`

Inference result payload on success. Null otherwise. May be any JSON value, including an object, array, string, number, boolean, or null.

### [error](#start-default-async-task-response-error)

- **Type**: `string (nullable)`

Unstructured error message when `status` is `failed`. Null otherwise. It reports a task the platform accepted and that then failed. Its wording is not part of this contract: it carries no stable code or retry signal, so do not parse it to classify a failure.

### [createdAt](#start-default-async-task-response-createdat)

- **Type**: `string (date-time)`
- **Required**: true
- **Format**: `date-time`

### [completedAt](#start-default-async-task-response-completedat)

- **Type**: `string (date-time) (nullable)`
- **Format**: `date-time`

### [Errors](#start-default-async-task-errors)

<table><tbody><tr><td data-rw-cid-pz7tphoj="true">Status</td><td data-rw-cid-pz7tphoj="true">When</td></tr><tr><td data-rw-cid-pz7tphoj="true"><code data-rw-cid-pz7tphoj="">400</code></td><td data-rw-cid-pz7tphoj="true">The request was malformed and could not be parsed (e.g. invalid JSON). A well-formed request that fails validation returns <code class="component-Code">422</code> instead.</td></tr><tr><td data-rw-cid-pz7tphoj="true"><code data-rw-cid-pz7tphoj="">401</code></td><td data-rw-cid-pz7tphoj="true">Missing or invalid credentials</td></tr><tr><td data-rw-cid-pz7tphoj="true"><code data-rw-cid-pz7tphoj="">403</code></td><td data-rw-cid-pz7tphoj="true">Authenticated but not permitted to access this resource</td></tr><tr><td data-rw-cid-pz7tphoj="true"><code data-rw-cid-pz7tphoj="">404</code></td><td data-rw-cid-pz7tphoj="true">The app does not exist, or it exists and does not declare the endpoint path. An undeclared endpoint carries <code class="component-Code">endpointPath</code> with the rejected path. Its absence means the app itself was not found.</td></tr><tr><td data-rw-cid-pz7tphoj="true"><code data-rw-cid-pz7tphoj="">409</code></td><td data-rw-cid-pz7tphoj="true">Resource already exists or the request conflicts with its current state</td></tr><tr><td data-rw-cid-pz7tphoj="true"><code data-rw-cid-pz7tphoj="">413</code></td><td data-rw-cid-pz7tphoj="true">The request body exceeds its size limit: 10 MiB on <code class="component-Code">invoke-sync</code> and <code class="component-Code">invoke-async</code>, whose body carries the endpoint's payload, and 1 MiB on the other operations that answer with this response. <code class="component-Code">detail</code> names the limit in bytes.</td></tr><tr><td data-rw-cid-pz7tphoj="true"><code data-rw-cid-pz7tphoj="">415</code></td><td data-rw-cid-pz7tphoj="true">The request body arrived with a Content-Type this operation does not accept. The body was not decoded, so this is not a schema failure. A body of <code class="component-Code">application/json</code> that cannot be parsed returns <code class="component-Code">400</code>. One that parses and breaks the schema returns <code class="component-Code">422</code>. A body sent with no Content-Type is the same refusal.</td></tr><tr><td data-rw-cid-pz7tphoj="true"><code data-rw-cid-pz7tphoj="">422</code></td><td data-rw-cid-pz7tphoj="true">The request was well-formed but semantically invalid (e.g. a missing or out-of-range field). A request that could not be parsed returns <code class="component-Code">400</code>. The <code class="component-Code">errors</code> array carries one entry per offending field.</td></tr><tr><td data-rw-cid-pz7tphoj="true"><code data-rw-cid-pz7tphoj="">500</code></td><td data-rw-cid-pz7tphoj="true">Unexpected server error</td></tr><tr><td data-rw-cid-pz7tphoj="true"><code data-rw-cid-pz7tphoj="">503</code></td><td data-rw-cid-pz7tphoj="true">The invocation could not be accepted and no task was minted. The problem <code class="component-Code">type</code> says which of two conditions applies, because the client's next move differs. <code class="component-Code">capacity-unavailable</code> means the app is deployed and correct, and the platform has no workload able to serve it: the app is short of the workers it asks for, or it has work waiting and nothing running it. The request is unchanged by the refusal and succeeds as sent once capacity returns, so retry it rather than correct it, after <code class="component-Code">Retry-After</code> where that header is present. Read <code class="component-Code">health.reason</code> on the app to tell the two capacity conditions apart. <code class="component-Code">service-unavailable</code> means something this route depends on is temporarily unreachable, or the organization's serverless tenancy is still being provisioned. That is retryable too, but it says nothing about the app.</td></tr></tbody></table>

## Get a task

GETapi.serverless.runware.ai/v1/apps/{appId}/tasks/{taskId}

Returns the task's current status, read through the inference transport layer from the shared result store. When `completed`, includes the result `output` and `completedAt`. When `failed`, includes `error`. When `pending`, neither is set. If the app is `stopped`, `deleting`, or `failed`, accepted task results stay readable. A `404 Not Found` means the task cannot currently be verified for this app. Because enqueue-time ownership tracking is best effort, a recently returned task ID can temporarily return `404`. Retry it within the normal polling window. Unknown or deleted apps also return `404 Not Found`.

### [Request](#get-task-request)

Path

### [appId](#get-task-path-appid)

- **Type**: `string`
- **Required**: true
- **Min**: `6`
- **Max**: `30`

Immutable app identifier, unique among the authenticated organization's live apps.

### [taskId](#get-task-path-taskid)

- **Type**: `string (uuid)`
- **Required**: true
- **Format**: `UUID v4`
- **Min**: `36`
- **Max**: `36`

Task identifier, supplied by the caller when the task was submitted.

### [Response](#get-task-response)

### [id](#get-task-response-id)

- **Type**: `string`
- **Required**: true

Task identifier, supplied by the caller when the task was submitted.

### [status](#get-task-response-status)

- **Type**: `string`
- **Required**: true

**Possible values**: `pending` `completed` `failed`

### [appId](#get-task-response-appid)

- **Type**: `string`
- **Required**: true
- **Min**: `6`
- **Max**: `30`

Immutable app identifier. Unique among the authenticated organization's live apps: it cannot be changed after creation, and it becomes available again once the app it named reaches `deleted`.

### [endpointPath](#get-task-response-endpointpath)

- **Type**: `string`
- **Required**: true
- **Min**: `1`
- **Max**: `255`

Path of the endpoint to route the task to: one or more bare lowercase segments joined by slashes, such as `generate` or `v1/chat/completions`, with no leading or trailing slash. Send those slashes unencoded. A generated client that escapes `/` as `%2F` is rejected with `422`.

### [output](#get-task-response-output)

- **Type**: `any`

Inference result payload on success. Null otherwise. May be any JSON value, including an object, array, string, number, boolean, or null.

### [error](#get-task-response-error)

- **Type**: `string (nullable)`

Unstructured error message when `status` is `failed`. Null otherwise. It reports a task the platform accepted and that then failed. Its wording is not part of this contract: it carries no stable code or retry signal, so do not parse it to classify a failure.

### [createdAt](#get-task-response-createdat)

- **Type**: `string (date-time)`
- **Required**: true
- **Format**: `date-time`

### [completedAt](#get-task-response-completedat)

- **Type**: `string (date-time) (nullable)`
- **Format**: `date-time`

### [Errors](#get-task-errors)

<table><tbody><tr><td data-rw-cid-pz7tphoj="true">Status</td><td data-rw-cid-pz7tphoj="true">When</td></tr><tr><td data-rw-cid-pz7tphoj="true"><code data-rw-cid-pz7tphoj="">401</code></td><td data-rw-cid-pz7tphoj="true">Missing or invalid credentials</td></tr><tr><td data-rw-cid-pz7tphoj="true"><code data-rw-cid-pz7tphoj="">404</code></td><td data-rw-cid-pz7tphoj="true">Resource not found</td></tr><tr><td data-rw-cid-pz7tphoj="true"><code data-rw-cid-pz7tphoj="">422</code></td><td data-rw-cid-pz7tphoj="true">The request was well-formed but semantically invalid (e.g. a missing or out-of-range field). A request that could not be parsed returns <code class="component-Code">400</code>. The <code class="component-Code">errors</code> array carries one entry per offending field.</td></tr><tr><td data-rw-cid-pz7tphoj="true"><code data-rw-cid-pz7tphoj="">500</code></td><td data-rw-cid-pz7tphoj="true">Unexpected server error</td></tr><tr><td data-rw-cid-pz7tphoj="true"><code data-rw-cid-pz7tphoj="">502</code></td><td data-rw-cid-pz7tphoj="true">An upstream service was unreachable or refused the request</td></tr><tr><td data-rw-cid-pz7tphoj="true"><code data-rw-cid-pz7tphoj="">503</code></td><td data-rw-cid-pz7tphoj="true">A required service is temporarily unavailable</td></tr></tbody></table>

## List tasks

GETapi.serverless.runware.ai/v1/apps/{appId}/tasks

Lists TTL-bounded asynchronous task metadata for this app so a client can recover task ids after an interrupted long-poll or CLI session. Pending includes queued, running and retrying work. Tasks appear only within the configured recovery window. A page can be empty and still have `nextCursor`. Continue until it is null. Pending entries are best effort and may disappear if the recovery store restarts. Tracked tasks reappear on completion. A `completed` task carries the same `output` that `GET /v1/apps/{appId}/tasks/{taskId}` returns for it. A page holds fewer than `limit` tasks when their outputs are large; continue with `nextCursor`. A task whose output cannot be read yet is listed as `pending`, as that read would report it, and is left out of a page filtered on `completed`. This is not persisted task history. A task id names one task, so resubmitting one does not add a second entry here. If the app is `stopped`, `deleting`, or `failed`, recovery stays available. Unknown or deleted apps return `404 Not Found`.

### [Request](#list-tasks-request)

Path

### [appId](#list-tasks-path-appid)

- **Type**: `string`
- **Required**: true
- **Min**: `6`
- **Max**: `30`

Immutable app identifier, unique among the authenticated organization's live apps.

Query

### [limit](#list-tasks-query-limit)

- **Type**: `integer`
- **Format**: `int32`
- **Min**: `1`
- **Max**: `100`
- **Default**: `20`

Maximum number of items to return.

### [cursor](#list-tasks-query-cursor)

- **Type**: `string`

Opaque pagination cursor returned by a previous call, as `nextCursor` or, on the operations that offer one, `prevCursor`.

### [status](#list-tasks-query-status)

- **Type**: `string`

**Allowed values**: `pending` `completed` `failed`

### [Response](#list-tasks-response)

### [nextCursor](#list-tasks-response-nextcursor)

- **Type**: `string (nullable)`

Cursor for the next page. Null when there are no more items.

### [data](#list-tasks-response-data)

- **Type**: `object[] (8 properties)`

#### [id](#list-tasks-response-data-id)

- **Type**: `string`
- **Required**: true

Task identifier, supplied by the caller when the task was submitted.

#### [status](#list-tasks-response-data-status)

- **Type**: `string`
- **Required**: true

**Possible values**: `pending` `completed` `failed`

#### [appId](#list-tasks-response-data-appid)

- **Type**: `string`
- **Required**: true
- **Min**: `6`
- **Max**: `30`

Immutable app identifier. Unique among the authenticated organization's live apps: it cannot be changed after creation, and it becomes available again once the app it named reaches `deleted`.

#### [endpointPath](#list-tasks-response-data-endpointpath)

- **Type**: `string`
- **Required**: true
- **Min**: `1`
- **Max**: `255`

Path of the endpoint to route the task to: one or more bare lowercase segments joined by slashes, such as `generate` or `v1/chat/completions`, with no leading or trailing slash. Send those slashes unencoded. A generated client that escapes `/` as `%2F` is rejected with `422`.

#### [output](#list-tasks-response-data-output)

- **Type**: `any`

Inference result payload on success. Null otherwise. May be any JSON value, including an object, array, string, number, boolean, or null.

#### [error](#list-tasks-response-data-error)

- **Type**: `string (nullable)`

Unstructured error message when `status` is `failed`. Null otherwise. It reports a task the platform accepted and that then failed. Its wording is not part of this contract: it carries no stable code or retry signal, so do not parse it to classify a failure.

#### [createdAt](#list-tasks-response-data-createdat)

- **Type**: `string (date-time)`
- **Required**: true
- **Format**: `date-time`

#### [completedAt](#list-tasks-response-data-completedat)

- **Type**: `string (date-time) (nullable)`
- **Format**: `date-time`

### [Errors](#list-tasks-errors)

<table><tbody><tr><td data-rw-cid-pz7tphoj="true">Status</td><td data-rw-cid-pz7tphoj="true">When</td></tr><tr><td data-rw-cid-pz7tphoj="true"><code data-rw-cid-pz7tphoj="">400</code></td><td data-rw-cid-pz7tphoj="true">The request was malformed and could not be parsed (e.g. invalid JSON). A well-formed request that fails validation returns <code class="component-Code">422</code> instead.</td></tr><tr><td data-rw-cid-pz7tphoj="true"><code data-rw-cid-pz7tphoj="">401</code></td><td data-rw-cid-pz7tphoj="true">Missing or invalid credentials</td></tr><tr><td data-rw-cid-pz7tphoj="true"><code data-rw-cid-pz7tphoj="">404</code></td><td data-rw-cid-pz7tphoj="true">Resource not found</td></tr><tr><td data-rw-cid-pz7tphoj="true"><code data-rw-cid-pz7tphoj="">422</code></td><td data-rw-cid-pz7tphoj="true">The request was well-formed but semantically invalid (e.g. a missing or out-of-range field). A request that could not be parsed returns <code class="component-Code">400</code>. The <code class="component-Code">errors</code> array carries one entry per offending field.</td></tr><tr><td data-rw-cid-pz7tphoj="true"><code data-rw-cid-pz7tphoj="">500</code></td><td data-rw-cid-pz7tphoj="true">Unexpected server error</td></tr><tr><td data-rw-cid-pz7tphoj="true"><code data-rw-cid-pz7tphoj="">502</code></td><td data-rw-cid-pz7tphoj="true">An upstream service was unreachable or refused the request</td></tr><tr><td data-rw-cid-pz7tphoj="true"><code data-rw-cid-pz7tphoj="">503</code></td><td data-rw-cid-pz7tphoj="true">A required service is temporarily unavailable</td></tr></tbody></table>