Tasks

Every generation and analysis call creates a task. Its three statuses, why a completed task can hold failed items, the ways to collect a result, and how long files last.

Every generation and analysis request creates a task. Mynth validates the request, holds the estimated cost on your balance, and returns a task id within milliseconds. The work runs after that, and you collect the result separately.

The SDK's generate(), rate(), and similar methods look synchronous because they create the task and poll it for you. The HTTP API has no synchronous generate call.

What creates a task#

RequestTask typeresult holds
POST /image/generateimage.generategenerated images
POST /image/remove-backgroundimage.remove_backgroundone cutout image
POST /image/rateimage.ratea content rating level
POST /image/altimage.altalt text
POST /image/reviewimage.reviewa quality score and findings
POST /video/generatevideo.generatea generated video

Each answers 201 with the task id and the held estimate:

{ "data": { "taskId": "tsk_01KE7XWWEQ4MCGWKBQKJ1G47RP", "estimatedCost": "0.03" } }

Task ids are tsk_ followed by a ULID, so they sort by creation time.

Statuses#

There are three. pending covers both queued and running, so there is no running status to wait for.

201 { taskId, estimatedCost }      estimate held on your balance
  │
  ▼
pending ──┬──▶ completed   result set, successful outputs charged
          └──▶ failed      errors set, hold released, nothing charged

A task settles once. It never leaves completed or failed, and Mynth never reruns a settled task. To try again, send a new request, which creates a new task and a new hold.

Completed does not mean every item worked#

image.generate with count: 4 runs four generations independently. When one fails, the task still completes, and each entry in result.images carries its own status:

{
  "status": "completed",
  "result": {
    "model": "black-forest-labs/flux.2-pro",
    "images": [
      {
        "status": "success",
        "id": "img_V1StGXR8Z5jdHi6BmyT0sC1pQ2rN4wLk",
        "url": "https://cdn.mynth.io/images/img_V1StGXR8Z5jdHi6BmyT0sC1pQ2rN4wLk.webp"
      },
      {
        "status": "failed",
        "error": {
          "code": "RESTRICTED_CONTENT",
          "message": "The request was blocked by content moderation."
        }
      }
    ]
  }
}

video.generate works the same way under result.videos. A provider refusal (RESTRICTED_CONTENT) or a model with no capacity (PROVIDERS_BUSY) fails the item, not the task, so a completed generation task can hold no usable output at all.

Always check the task status, then every item. Only failed items are free: you pay for the images that succeeded.

The other task types (image.remove_background, image.rate, image.alt, image.review) have no items. When their work fails, the task is failed.

In the SDK, urls and getImages() skip failed images without saying so. If a partial result is not acceptable, compare getImages().length with the count you sent.

Collecting the result#

Pick one of three:

ApproachUse it when
Wait in the SDK or CLIThe code can hold a connection: a script, a worker, a job queue
PollYou want control over the loop, or a browser does the waiting
WebhookNothing can wait: serverless handlers, long video renders

A destination changes where the file is stored, not how you learn the task finished, so combine it with one of the three.

The SDK polls on a fixed schedule and gives up after 30 minutes for images and an hour for video. Tasks and polling has the exact intervals. GET /tasks/{id}/status and GET /tasks/{id}/result are served from a cache, so point a polling loop at them rather than at GET /tasks/{id}.

Reading a task#

CallReturns
GET /tasks/{id}/statusstatus only
GET /tasks/{id}/resultid, type, status, result
GET /tasks/{id}The full record: request, result, errors, cost, and more
GET /tasksRecent tasks, newest first, without request or result

GET /tasks with an API key lists only the tasks that key created. Any key on your account with the generate scope can read any of your tasks by id. The task object documents every field.

Retries and timeouts#

Mynth retries before a failure reaches you:

WorkAttemptsTime budgetEach attempt
One image435 minutespicks a provider again
One video332 minutesup to 15 minutes

A failing provider therefore fails over rather than failing the image. RESTRICTED_CONTENT, INVALID_PROMPT, INVALID_INPUT, and CAPABILITY_NOT_SUPPORTED are not retried, because another attempt would fail the same way. Errors lists every code and whether retrying helps.

A task still pending 24 hours after its last update is failed with TASK_EXPIRED by a daily sweep, and its hold is released. Pricing has the details.

File lifetimes#

FileServed for
A generated image or video7 days
An image uploaded with /image/upload1 day

Mynth hands you a URL because that is the practical way to use the file. The id in it is long and random, but Mynth is not a file host. To keep a file, name a destination so Mynth writes it to your own storage, or copy it when the webhook arrives or polling shows completed.

When copying on a machine with little memory, stream the download into the upload instead of buffering the whole file.

Next steps#