NOUKAI

Calling Your Flow

How to call your published flow — sync vs async execution, error handling, and response format.

Once your flow is published and set as production, call it via the slug URL.

Sync Execution

Blocks until the flow completes. Best for flows that run in under 30 seconds.

POST /api/v1/seq/{org}/{project}/{flow}/execute

Request

{
  "message": "Input text for the flow",
  "parameters": {
    "custom_key": "custom_value"
  },
  "attachments": [],
  "block_overrides": {}
}
FieldTypeRequiredDescription
messagestringYesPrimary input text
parametersobjectNoAdditional key-value parameters
attachmentsarrayNoMedia inputs (e.g. image URLs). See With Attachments below.
block_overridesobjectNoPer-step field overrides

Response (200)

{
  "status": "completed",
  "result": { "...flow output..." },
  "flowId": "uuid",
  "blockCount": 3
}

Async Execution

Returns immediately with an execution ID. Best for long-running flows.

POST /api/v1/seq/{org}/{project}/{flow}/jobs

Response (202)

{
  "executionId": "exec-uuid",
  "status": "started",
  "flowId": "uuid",
  "blockCount": 3
}

Polling for Results

GET /api/v1/seq/{org}/{project}/{flow}/jobs/{executionId}

Poll until status is completed or failed.

Step-Through (Pause Between Steps)

For UIs that show each step's output before continuing — or that let users edit a block's output / prompt mid-run — use the step-through endpoint:

POST /api/v1/seq/{org}/{project}/{flow}/step

The server stays stateless between calls; your client carries the cursor and accumulated outputs. See Step-Through Execution for the client loop and full TypeScript / Python examples.

With Attachments

Pass image URLs alongside message to feed media into vision-capable LLM blocks. Noukai never stores the bytes — your file lives on your CDN, S3 bucket, or any HTTPS host that OpenRouter can reach.

For the full attachment object schema, supported MIME types, error codes, and a deeper walkthrough see Using Attachments. The minimum example:

{
  "message": "What's in this screenshot?",
  "attachments": [
    {
      "kind": "url",
      "url": "https://customer-cdn.example.com/uploads/screenshot.png",
      "mime_type": "image/png"
    }
  ]
}

The block's model must support the attached MIME type. If it doesn't, the request is rejected with 400 MODEL_MIME_INCOMPATIBLE before any work runs. Use a vision-capable model on any LLM block that needs to see the image.

async function callFlowWithImage(message: string, imageUrl: string) {
  const res = await fetch(
    `${process.env.NOUKAI_API_URL}/api/v1/seq/my-org/my-project/my-flow/execute`,
    {
      method: "POST",
      headers: {
        Authorization: `Bearer ${process.env.NOUKAI_API_KEY}`,
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        message,
        attachments: [
          { kind: "url", url: imageUrl, mime_type: "image/png" },
        ],
      }),
    },
  );
 
  if (!res.ok) {
    const detail = await res.json().catch(() => null);
    throw new Error(
      `API error ${res.status}: ${detail?.detail?.code ?? res.statusText}`,
    );
  }
 
  const data = await res.json();
  return data.result;
}

Versioned Calls

Call a specific version instead of the production version:

POST /api/v1/seq/{org}/{project}/{flow}/v2/execute
POST /api/v1/seq/{org}/{project}/{flow}/v3/jobs

Error Handling

StatusMeaningAction
200SuccessParse result
202Accepted (async)Poll for results
401UnauthorizedCheck API key
404Flow not foundVerify slug and that flow is published
422Validation errorCheck request body format
500Execution errorCheck flow configuration

A 200 response with "status": "failed" means the flow executed but encountered an error during processing. Check the result field for error details.

Code Examples

async function callFlow(message: string, params = {}) {
  const res = await fetch(
    `${process.env.NOUKAI_API_URL}/api/v1/seq/my-org/my-project/my-flow/execute`,
    {
      method: "POST",
      headers: {
        Authorization: `Bearer ${process.env.NOUKAI_API_KEY}`,
        "Content-Type": "application/json",
      },
      body: JSON.stringify({ message, parameters: params }),
    }
  );
 
  if (!res.ok) {
    throw new Error(`API error: ${res.status} ${res.statusText}`);
  }
 
  const data = await res.json();
  if (data.status === "failed") {
    throw new Error(`Flow execution failed: ${JSON.stringify(data.result)}`);
  }
 
  return data.result;
}

On this page