Jobs and executions
Poll, list, cancel and delete Nodaro runs from TypeScript. client.jobs tracks single generations, and client.executions tracks whole workflow runs.
A job is one generation in Nodaro, such as one image, one video render or one voiceover, and an execution is one run of a whole workflow. client.jobs reads, lists, cancels and deletes jobs, and client.executions reads, lists and cancels workflow runs. client.videoPro stops or continues a long Generate Video Pro run. The methods call the same endpoints as the Jobs and Executions REST APIs.
Methods
| Method | What it does |
|---|---|
executions.get(id) | Read a workflow run, with the state of every node |
executions.listForWorkflow(workflowId, params?) | List the runs of a workflow |
executions.cancel(id, params?) | Stop a workflow run |
jobs.get(id) | Read a job with its input and output |
jobs.list(params?) | List your jobs, newest first |
jobs.getStatus(id) | Read the status of a job, for polling |
jobs.cancel(id) | Stop a job and refund its reserved credits |
jobs.delete(id) | Delete a job and the media it produced |
videoPro.stop(jobId) | Stop a Generate Video Pro run and keep what is done |
videoPro.continueRun(jobId, opts?) | Continue a Generate Video Pro run as a new job |
Statuses
A job moves through these statuses:
| Job status | Meaning |
|---|---|
pending, queued | Waiting for a worker. |
processing | Running. progress goes from 0 to 100 when the model reports it. |
pending_review | Held for human review by a content policy of this deployment. Not an end state. |
completed | Done. output_data holds the result. |
failed | Failed. error_message explains why, and error_hint may classify it. |
cancelled | Stopped by a cancel. |
An execution has its own statuses: pending, running, completed, failed, cancelled, stopping, timed_out and discarded. Each node inside it is pending, running, completed, failed or skipped.
client.executions
An execution is one run of a workflow. It groups one job per AI node and the state of every node.
executions.get(id)
Reads a workflow run, including a map of every node's state. When the id belongs to a single-node job instead of a workflow run, the server answers with the same shape for that one node.
get(id: string): Promise<{ data: WorkflowExecution }>Prop
Type
const { data } = await client.executions.get(executionId)
console.log(data.status, `${data.completedNodes}/${data.totalNodes}`, data.totalCreditsUsed)A WorkflowExecution has id, workflowId, status, triggerType (manual, webhook, schedule, app_run or single-node), nodeStates, totalNodes, completedNodes, failedNodes, totalCreditsUsed, errorMessage, startedAt, completedAt, createdAt and updatedAt.
Reading a node's output. nodeStates[nodeId].output is present when the node completed. It can also be present when the node failed but the run kept a usable result, as the 3D scene nodes do. Check the field, not the status, and never treat a present output as success:
import { nodeStateMayCarryOutput } from "@nodaro/sdk"
const node = data.nodeStates["scene-1"]
if (node.status === "failed") {
console.error(node.error) // the failure stands
if (node.output?.plan) {
// the draft the run kept is still here, and it was billed
}
}
nodeStateMayCarryOutput(node.status) // true for "completed" and "failed"OUTPUT_BEARING_NODE_STATUSES, the set of those two statuses, is exported too.
executions.listForWorkflow(workflowId, params?)
Lists the runs of one workflow, newest first, a page at a time. The list includes single-node runs started on that workflow.
listForWorkflow(workflowId: string, params?: ListExecutionsForWorkflowParams): Promise<{
data: WorkflowExecutionSummary[]
nextCursor?: string
}>Prop
Type
const { data: runs, nextCursor } = await client.executions.listForWorkflow(workflowId, {
limit: 20,
status: "completed",
})executions.cancel(id, params?)
Stops a workflow run. There are three ways to stop it:
- Immediately (the default): running jobs are cancelled, their reserved credits are refunded, and the status becomes
cancelled. mode: "after_current": the status becomesstopping. Running nodes finish and land on the canvas and in your library, then the run stops.mode: "discard": no new nodes start, but running jobs are not cancelled, because an external model call cannot be stopped halfway. They finish and are saved to your library, but their results do not return to the canvas. The status becomesdiscarded, and there is no refund, because the jobs completed.
cancel(id: string, params?: { mode?: "after_current" | "discard" }): Promise<{ success: true }>Prop
Type
await client.executions.cancel(executionId, { mode: "after_current" })client.jobs
A job is one generation: one image, one video render, one voiceover. A workflow run creates one job per AI node, and every single-node run creates one job. Job fields use snake_case, as the API sends them.
jobs.get(id)
Reads a job, including its input and output.
get(id: string): Promise<{ data: Job }>Prop
Type
const { data: job } = await client.jobs.get(jobId)
if (job.status === "completed") console.log(job.output_data)A Job has these fields:
| Field | Description |
|---|---|
id, status, progress | The job id, its status and its progress from 0 to 100. |
input_data, output_data | The request and the result. Server-only values are removed from both. |
error_message | Why the job failed, or null. |
error_hint | A structured reason for some failures. See below. |
credits | The credits reserved for the job, or null. |
credit_status | reserved, committed or refunded: where the credits stand. null for a job without a charge. |
job_type | The kind of job. |
created_at, started_at, completed_at | Timestamps. |
user_id | The owner. |
source, source_detail | Where the job came from: sdk, cli, mcp, app, web, api and more, with a detail such as sdk/2.17.0. |
recovering | true while the platform recovers a job whose worker stopped after the model delivered. |
error_hint has two kinds. Narrow on kind before you read the rest:
safety-block: the model's own safety filter refused the output.classiscopyright,likenessorsafety.retriedsays whether Nodaro already retried once, andsuggestedProvider, when present, names a model you can retry the same request on. See When a model blocks the prompt.policy-block: a content policy of this deployment rejected the request or the result.reasonis written for users, so show it as it is.
jobs.list(params?)
Lists your jobs, newest first, a page at a time (GET /v1/jobs).
list(params?: { type?: string; origin?: string; limit?: number; cursor?: string }): Promise<{
data: Job[]
next: string | null
}>Prop
Type
let cursor: string | undefined
do {
const page = await client.jobs.list({ type: "llm-structured", origin: "my-app", cursor })
for (const job of page.data) console.log(job.id, job.status)
cursor = page.next ?? undefined
} while (cursor)A page can hold fewer rows than limit, even none, and still have a next. Page on next, never on the number of rows.
jobs.getStatus(id)
Reads only the status of a job: id, status, progress, output_data, error_message, error_hint and credit_status (GET /v1/jobs/:id/status). It skips the request data and the cost fields, so it is much lighter than get(). Use it in polling loops.
getStatus(id: string): Promise<{ data: JobStatusResult }>Prop
Type
async function waitForJob(jobId: string) {
for (;;) {
const { data } = await client.jobs.getStatus(jobId)
if (data.status === "completed") return data.output_data
if (data.status === "failed" || data.status === "cancelled") {
throw new Error(data.error_message ?? data.status)
}
await new Promise((resolve) => setTimeout(resolve, 2_000))
}
}client.nodes.runAndWait() runs this loop for you, with progress, cancellation and typed errors.
jobs.cancel(id)
Cancels a job and refunds the credits it had reserved. A job held for review can be cancelled too.
cancel(id: string): Promise<{ success: true; cancelled: number }>Prop
Type
const { cancelled } = await client.jobs.cancel(jobId)jobs.delete(id)
Deletes a job and the private media it produced (DELETE /v1/jobs/:id). Only the job's owner may delete it. A running job is deleted as it is, so cancel it first when its worker should stop.
delete(id: string): Promise<{ success: true }>Prop
Type
await client.jobs.cancel(jobId)
await client.jobs.delete(jobId)client.videoPro
Run control for Generate Video Pro, the node that renders long videos in segments. It works on Nodaro Cloud. Start the run like any node run, then use these methods on its job.
videoPro.stop(jobId)
Stops a running Generate Video Pro job gracefully. The segment in progress is abandoned and still billed, and the remaining segments are skipped. The finished segments are joined into the job's final video, and the unused reserve is refunded. A job that has not started yet is cancelled with a full refund.
stop(jobId: string): Promise<StopVideoProResult>Prop
Type
await client.videoPro.stop(jobId)
const { data } = await client.jobs.getStatus(jobId) // becomes completed, with the partial videoKeep polling the job. It completes with output_data.pro.stopped set to true.
videoPro.continueRun(jobId, opts?)
Continues a stopped, failed or completed run as a new job. Segments before fromSegment are reused, and every segment from it on is generated again. You pay only for the regenerated segments plus the flat Pro fee.
continueRun(jobId: string, opts?: { fromSegment?: number }): Promise<ContinueVideoProResult>Prop
Type
const { jobId: newJobId, fromSegment } = await client.videoPro.continueRun(jobId, { fromSegment: 4 })The result carries the new jobId to poll, and may carry continuedFromJobId, fromSegment, segmentCount and deduped.
Frequently asked questions
Related
Run nodes
Workflows and projects
Errors
Jobs
Executions
Last updated on
Workflows and projects
Create, update, share, export, import and run Nodaro workflows from TypeScript with client.workflows, and organize them in projects with client.projects.
Run nodes
Run any Nodaro node from TypeScript without a workflow. Discover node types, start runs, wait for results, and pass references and camera direction.