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#
| Member | Holds |
|---|---|
id | The 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#
| Wait | Interval | Gives up after |
|---|---|---|
| Images and tools | every 2.5 s for the first 12 s, then every 5 s | 30 minutes |
video.generate() | every 10 s | 1 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.
publicAccessTokencan be missing if Mynth failed to sign one. Fall back to polling from the server.wait()is for the server. Its last call isGET /tasks/{id}, which apat_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#
- Errors: what
wait()throws, and how to read the code. - Webhooks: take the result without a polling loop.
- Poll for results: the REST loop.