Poll for results
Poll a task's status until it settles, then read the result, from a server with an API key or from a browser with the task's pat_ token.
A create call returns a task id, not the file. Poll GET /tasks/{id}/status
until status leaves pending, then read GET /tasks/{id}/result. Both are
served from a cache and are the calls meant for a loop. GET /tasks/{id} is
the full record and is not.
The SDK's generate() does this for you. Poll yourself when you want control
over the loop, or when a browser does the waiting.
From a server#
const API = "https://api.mynth.io";
const headers = { Authorization: `Bearer ${process.env.MYNTH_API_KEY}` };
async function waitForTask(taskId: string, { timeoutMs = 30 * 60_000 } = {}) {
const deadline = Date.now() + timeoutMs;
let delay = 2_000;
while (Date.now() < deadline) {
const res = await fetch(`${API}/tasks/${taskId}/status`, { headers });
if (!res.ok && res.status < 500) throw new Error(`status ${res.status}`);
if (res.ok) {
const { data } = await res.json();
if (data.status !== "pending") {
const result = await fetch(`${API}/tasks/${taskId}/result`, { headers });
return (await result.json()).data; // { id, type, status, result }
}
}
await new Promise((resolve) => setTimeout(resolve, delay));
delay = Math.min(delay * 1.5, 10_000);
}
throw new Error(`Task ${taskId} still pending after ${timeoutMs} ms`);
}Start near 2 seconds and back off to about 10. Most images finish in seconds.
Video takes minutes, so give it a longer timeout. Retry 5xx and network
errors. A 4xx fails the same way every time.
When the loop returns:
status: "completed": checkstatuson each item inresult.imagesorresult.videos, because a completed task can hold failed items. See tasks.status: "failed":/resultdoes not includeerrors. ReadGET /tasks/{id}for the codes.
Copy the file when you see completed if you need it for more than 7 days
and did not name a destination.
From a browser#
POST /image/generate, POST /image/remove-background, and
POST /video/generate return data.access.publicAccessToken, a pat_ token
for that one task. It works as a bearer token on the status and result calls
for that task and nowhere else, and it expires one hour after it is issued.
Only those two paths accept cross-origin requests.
Create the task on your server and hand the browser only the id and the token:
// server
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",
});
return Response.json({ taskId: pending.id, token: pending.access.publicAccessToken });// browser
async function pollInBrowser(taskId: string, token: string) {
const headers = { Authorization: `Bearer ${token}` };
for (;;) {
const res = await fetch(`https://api.mynth.io/tasks/${taskId}/status`, { headers });
if (res.status === 401) throw new Error("Token expired or invalid. Ask the server again.");
const { data } = await res.json();
if (data.status !== "pending") {
const result = await fetch(`https://api.mynth.io/tasks/${taskId}/result`, { headers });
return (await result.json()).data;
}
await new Promise((resolve) => setTimeout(resolve, 3_000));
}
}- Treat
accessas optional. If Mynth could not sign a token, the task is still created andaccessis missing. Fall back to polling from the server. - An expired token answers
401 TOKEN_EXPIRED. A long video render can outlive the hour, so use a webhook or server-side polling for those. - Send
"access": { "pat": { "enabled": false } }on the create request to skip issuing a token.
Never send the mak_ key to the browser. The pat_ token can read one task's status and result
and do nothing else.
From the CLI#
npx @mynthio/cli task wait tsk_01KE7XWWEQ4MCGWKBQKJ1G47RP --jsontask wait prints the finished task. A failed task prints too, with a
non-zero exit code: 5 for RESTRICTED_CONTENT and 1 for anything else.
The default timeout is 30 minutes. Change it with --timeout <seconds>.
Next steps#
- Webhooks: get called instead of polling.
- Tasks and polling: how the SDK waits.
- The task object: the status and result responses.