Tasks and polling

Wait with generate(), return early with generateAsync(), how long the SDK polls, and how to hand a browser the pat_ token.

Every SDK call that does work creates a task. generate() polls that task for you. generateAsync() returns a TaskAsync right after the task is created, and you decide who waits.

import Mynth from "@mynthio/sdk";

const mynth = new Mynth();

const pending = await mynth.image.generateAsync({
  model: "black-forest-labs/flux.2-pro",
  prompt: "A lighthouse at dusk, film grain",
});

console.log(pending.id); // tsk_...
const task = await pending.wait();
console.log(task.urls[0]);

image.generate() is generateAsync() followed by wait(). The tools follow the same pattern: rate() and rateAsync(), alt() and altAsync(), review() and reviewAsync(), removeBackground() and removeBackgroundAsync(), video.generate() and video.generateAsync(). upload() and video.estimate() do not create tasks.

TaskAsync#

MemberHolds
idThe task id
access{ publicAccessToken? }, the browser token when the endpoint issues one
wait()Polls until the task settles, then returns the result class

wait() polls until completed, then loads the full task and builds the result. Calling it twice returns the same promise. A task that settles as failed makes it throw TaskAsyncTaskFailedError. Errors lists every throw.

How long it polls#

WaitIntervalGives up after
Images and toolsevery 2.5 s for the first 12 s, then every 5 s30 minutes
video.generate()every 10 s1 hour

Each sleep adds up to 500 ms of jitter. After the budget runs out, wait() throws TaskAsyncTimeoutError. The task itself keeps running, and you can still read it by id. Status reads that fail with a network error, a 404, or a 5xx are retried, up to 20 in a row.

Hold the connection only where that wait is acceptable, such as a script or a background worker. A request handler should store pending.id, respond, and finish in a webhook.

Poll from the browser#

image.generateAsync(), image.removeBackgroundAsync(), and video.generateAsync() expose the task's pat_ token as pending.access.publicAccessToken. Rate, alt text, and review do not issue one.

// server
const pending = await mynth.image.generateAsync({
  model: "black-forest-labs/flux.2-pro",
  prompt: "A lighthouse at dusk, film grain",
});

return Response.json({ taskId: pending.id, token: pending.access.publicAccessToken });

The browser calls GET /tasks/{id}/status and GET /tasks/{id}/result with Authorization: Bearer pat_.... Poll for results has the browser loop.

  • The token works only on those two routes and expires one hour after it is issued. A long video render can outlive it.
  • publicAccessToken can be missing if Mynth failed to sign one. Fall back to polling from the server.
  • wait() is for the server. Its last call is GET /tasks/{id}, which a pat_ cannot make.

Partial results#

urls, getImages(), and getVideos() skip failed items. Compare getImages().length with count when a short list is a problem. A video request renders one video, so a failed render shows up as an empty urls on a completed task. Tasks explains why a completed task can hold failed items.

Next steps#