The task object

Every field of a task, the result shape for each task type, and what the create, list, status, and result endpoints return.

Every generation and analysis call creates a task, and every task endpoint returns some part of this object. The lifecycle, billing, and file lifetimes are on tasks.

Where each part comes from#

CallReturns
A POST that creates a tasktaskId, estimatedCost, sometimes access. See create response
GET /tasksA page of rows: id, type, status, cost, timestamps
GET /tasks/{id}The full object
GET /tasks/{id}/statusstatus only
GET /tasks/{id}/resultid, type, status, result
A webhook deliverytask.id, request, and result or errors. See webhook payloads

Poll /status, then read /result. Both are served from a cache and accept a pat_ token. GET /tasks/{id} reads the database and needs an API key.

The object#

{
  "data": {
    "id": "tsk_01KE7XWWEQ4MCGWKBQKJ1G47RP",
    "type": "image.generate",
    "status": "completed",
    "request": {
      "model": "black-forest-labs/flux.2-pro",
      "prompt": "A lighthouse at dusk, film grain",
      "count": 1,
      "metadata": { "orderId": "ord_42" }
    },
    "result": {
      "model": "black-forest-labs/flux.2-pro",
      "images": [
        {
          "status": "success",
          "id": "img_V1StGXR8Z5jdHi6BmyT0sC1pQ2rN4wLk",
          "url": "https://cdn.mynth.io/images/img_V1StGXR8Z5jdHi6BmyT0sC1pQ2rN4wLk.webp",
          "mynth_url": "https://cdn.mynth.io/images/img_V1StGXR8Z5jdHi6BmyT0sC1pQ2rN4wLk.webp",
          "size": "1536x1024",
          "format": "webp"
        }
      ]
    },
    "errors": null,
    "cost": "0.03000000",
    "userId": "user_01JD8G3W1R5T6Y7U8I9O0P1Q2W",
    "apiKeyId": "ak_01KE7XWWEQ4MCGWKBQKJ1G47RP",
    "createdAt": "2026-07-04T10:00:00.000Z",
    "updatedAt": "2026-07-04T10:00:12.000Z"
  }
}
FieldTypeNotes
idstringtsk_ + a ULID. Sorts by creation time
typestringOne of the six task types. Decides the shape of request and result
statuspending | completed | failedpending covers queued and running. A settled task never changes again
requestobjectThe body as accepted, with defaults filled in. See request
resultobject | nullSet only when completed. Shape depends on type
errors[{ code, message? }] | nullSet only when failed
costdecimal string | nullUSD charged, 8 decimal places. Set only when completed
userIdstringThe account that owns the task
apiKeyIdstring | nullThe key that created it. null for dashboard and playground tasks
createdAtISO 8601 stringUTC
updatedAtISO 8601 stringUTC. The last change

The combinations are fixed:

statusresulterrorscost
pendingnullnullnull
completedsetnullset
failednullat least one entrynull

A completed generation can still hold failed items. Check each entry in result.images or result.videos. Errors lists the codes.

Money is always a decimal string: cost, estimatedCost, and a video's own cost. Add amounts up with a decimal type, not floats.

Request#

request echoes the body after validation:

  • Defaults are filled in, such as model: "auto" and count: 1 on image.generate, or effort: "high" on image.review.
  • Fields the schema does not know are gone. If a setting seems ignored, look here.
  • metadata comes back unchanged, here and in every webhook. Put your own ids in it to match a task to your records.
  • URLs in webhook.custom are shortened to the scheme, host, and first 12 characters of the path, because they often carry a token.

Each endpoint page under Endpoints lists the fields its task type accepts.

Task types#

typeCreated byresult holds
image.generatePOST /image/generatemodel, images[], magic_prompt?
image.remove_backgroundPOST /image/remove-backgroundimage
image.ratePOST /image/ratelevel
image.altPOST /image/altalt
image.reviewPOST /image/reviewscore, summary, findings, strengths
video.generatePOST /video/generatemodel, videos[]

Fields marked ? are absent, not null, when they do not apply.

image.generate#

{
  "model": "black-forest-labs/flux.2-pro",
  "images": [
    {
      "status": "success",
      "id": "img_V1StGXR8Z5jdHi6BmyT0sC1pQ2rN4wLk",
      "url": "https://assets.example.com/renders/img_V1StGXR8Z5jdHi6BmyT0sC1pQ2rN4wLk.webp",
      "mynth_url": "https://cdn.mynth.io/images/img_V1StGXR8Z5jdHi6BmyT0sC1pQ2rN4wLk.webp",
      "size": "1536x1024",
      "format": "webp",
      "rating": { "status": "success", "level": "sfw" }
    },
    {
      "status": "failed",
      "error": {
        "code": "RESTRICTED_CONTENT",
        "message": "The request was blocked by content moderation."
      }
    }
  ],
  "magic_prompt": { "positive": "A lone lighthouse on a rocky shore at dusk, ..." }
}
FieldTypeNotes
modelstringThe model that ran. With auto, the one Mynth picked
imagesarrayOne entry per requested image, each success or failed
magic_prompt?{ positive, negative? }The rewritten prompt, when the request set magic_prompt: true

A successful image:

FieldTypeNotes
status"success"
idstringimg_ + 32 random characters
urlstring | nullYour storage when a destination was named, else the same as mynth_url. null if that upload failed
mynth_urlstringMynth's copy. Always set, served for 7 days
sizestringMeasured from the file, {width}x{height}
formatpng | jpg | webpWhat output.format asked for, or what the provider returned
rating?objectWhen the request set rating: { status: "success", level } or { status: "failed", error: { code } }

A failed image is { "status": "failed", "error": { "code", "message?" } } with nothing else, and is not charged. Generated images carry no destination block, so a failed upload shows only as url: null.

image.remove_background#

{
  "image": {
    "id": "img_Q8mZr2LkT0vWc5NhY7pD3xFa9GsJ1bEu",
    "url": "https://cdn.mynth.io/images/img_Q8mZr2LkT0vWc5NhY7pD3xFa9GsJ1bEu.png",
    "mynth_url": "https://cdn.mynth.io/images/img_Q8mZr2LkT0vWc5NhY7pD3xFa9GsJ1bEu.png",
    "size": "1024x1024",
    "format": "png"
  }
}

image has the fields of a successful image.generate entry, without status and rating. format is png or webp. There is no per-item failure: if the work fails, the task is failed.

When the request named a destination, image also carries destination: { status: "success", name }, or { status: "failed", name, error: { code, message?, provider_response? } } next to url: null.

image.rate#

{ "level": "sfw" }

level is sfw or nsfw by default, or one of your value strings with custom levels.

image.alt#

{ "alt": "A white lighthouse on dark rocks, lit by an orange sunset sky" }

alt is 1 to 160 characters.

image.review#

{
  "score": 3,
  "summary": "Clean composition with one visible defect in the left hand.",
  "findings": [
    {
      "finding": "The left hand has six fingers",
      "category": "anatomy",
      "severity": "major",
      "where": "Bottom left, the hand resting on the railing",
      "confidence": "high"
    }
  ],
  "strengths": [{ "strength": "Warm, consistent lighting", "confidence": "medium" }]
}
FieldTypeNotes
scorenumber, 1 to 4Median of the reviewers' scores. Higher is better
summarystringA short prose summary
findings[].categorystringUsually anatomy, text, composition, artifact, color, or lighting. An open set
findings[].severitycritical | major | minor
findings[].confidencelow | medium | highReviewer agreement: bare threshold, majority, strong consensus
strengths[]{ strength, confidence }Same confidence scale

video.generate#

{
  "model": "bytedance/seedance-2.0-mini",
  "videos": [
    {
      "status": "success",
      "id": "vid_3HkP9wQz7LmR2tXc8VbN5dFy0JsA4gUe",
      "url": "https://cdn.mynth.io/videos/vid_3HkP9wQz7LmR2tXc8VbN5dFy0JsA4gUe.mp4",
      "mynth_url": "https://cdn.mynth.io/videos/vid_3HkP9wQz7LmR2tXc8VbN5dFy0JsA4gUe.mp4",
      "cost": "0.40500000",
      "duration": 5,
      "resolution": "720p",
      "audio": true
    }
  ]
}
FieldTypeNotes
idstringvid_ + 32 random characters
urlstringNever null. Video has no destinations
mynth_urlstringThe same as url today
costdecimal stringWhat this video cost
durationnumberSeconds
resolution480p | 720p | 1080p | 4k
audiobooleanWhether the video has generated audio

A failed video is { "status": "failed", "error": { "code", "message?" } }, like a failed image.

Create response#

Every POST that creates a task answers 201:

{
  "data": {
    "taskId": "tsk_01KE7XWWEQ4MCGWKBQKJ1G47RP",
    "estimatedCost": "0.03",
    "access": { "publicAccessToken": "pat_eyJhbGciOiJIUzI1NiJ9..." }
  }
}
FieldNotes
taskIdPass it to every task endpoint
estimatedCostUSD held on your balance until the task settles. The final cost is normally equal or lower
access.publicAccessToken?Image generate, remove background, and video generate only. Rules

The media is never in this response. Wait for the task with polling or a webhook.

Listing tasks#

GET /tasks returns the calling key's tasks, newest first. Rows omit request and result, so fetch a task by id for those.

QueryDefaultNotes
limit201 to 100
afternoneA task id. Returns tasks older than it
{
  "data": [
    {
      "id": "tsk_01KE7XWWEQ4MCGWKBQKJ1G47RP",
      "type": "image.generate",
      "status": "completed",
      "cost": "0.03000000",
      "createdAt": "2026-07-04T10:00:00.000Z",
      "updatedAt": "2026-07-04T10:00:12.000Z"
    }
  ]
}

There is no hasMore and no total. To page, pass the last id you received as after. A page shorter than limit is the last one.

let after: string | undefined;

do {
  const url = new URL("https://api.mynth.io/tasks");
  url.searchParams.set("limit", "100");
  if (after) url.searchParams.set("after", after);

  const res = await fetch(url, {
    headers: { Authorization: `Bearer ${process.env.MYNTH_API_KEY}` },
  });
  const { data } = await res.json();

  for (const task of data) console.log(task.id, task.status, task.cost);

  after = data.length === 100 ? data.at(-1).id : undefined;
} while (after);

After a create request times out, look here before resending. If the task is listed, it was created, and sending the request again would create and charge a second one.

Status and result#

{ "data": { "status": "pending" } }
{
  "data": {
    "id": "tsk_01KE7XWWEQ4MCGWKBQKJ1G47RP",
    "type": "image.alt",
    "status": "completed",
    "result": { "alt": "A white lighthouse on dark rocks, lit by an orange sunset sky" }
  }
}

/result answers 200 while the task is pending, with result: null. It never includes errors, so for a failed task read GET /tasks/{id}.

Next steps#

  • Tasks: statuses, billing, retries, and file lifetimes.
  • Webhook payloads: the same result, pushed to you.
  • Errors: the codes in errors and on failed items.