API reference

Client SDKs and API

Official Python, .NET, Java and Node.js clients, generated from the live OpenAPI document.

Flow Current 4 min read Updated

Any service in your organisation can start and monitor workflows through the Kiwi Flow API. Four official client libraries wrap it, so your application code stays separate from workflow logic.

Language Package
Python Python SDK
.NET / C# .NET SDK
Java Java SDK
Node.js Node.js SDK

The SDKs are generated from the platform's OpenAPI description, which is exported from the running API at build time. They cover every resource area of the API: authentication, users and API keys, roles, groups and permissions, workflows (create, run, publish, validate, versions, shares), triggers, runs, approval and external tasks, connections, templates, storage, AI generation and assistants, licensing, resource guards, the activity catalogue, OAuth2 authorisation and the audit log.

Note

The SDKs are currently pre-release (version 0.2.0) and are not yet published to the public package registries. Ask Kiwify Labs for access, or build each SDK from its folder in the Kiwi Flow source. The install commands below apply once the packages are published.

Install#

.NET
dotnet add package KiwiFlow.Client
Java
# from the SDK folder: install the client into your local Maven repository
mvn clean install
# then depend on com.kiwify.flow:kiwiflow-client:0.2.0
Node.js
npm install kiwiflow --save
Python
pip install kiwiflow

The .NET SDK targets .NET 10. Choose your language in any sample below; the choice applies to every sample on the site and is remembered in your browser.

Authenticate and connect#

Create an API key for a user (kiwi flow key-add) and pass it to the client as a bearer token. Keep keys in a secret store, never in source control.

.NET
using KiwiFlow.Client.Api;
using KiwiFlow.Client.Client;
using KiwiFlow.Client.Extensions;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

var host = Host.CreateDefaultBuilder(args)
    .ConfigureApi((context, options) =>
    {
        options.AddTokens(new BearerToken(apiKey));
        options.AddApiHttpClients(client =>
        {
            client.BaseAddress = new Uri("https://your-kiwiflow-host");
        });
    })
    .Build();

var workflowsApi = host.Services.GetRequiredService<IWorkflowsApi>();
var runsApi = host.Services.GetRequiredService<IRunsApi>();
Java
import com.kiwify.flow.client.ApiClient;
import com.kiwify.flow.client.Configuration;
import com.kiwify.flow.client.api.RunsApi;
import com.kiwify.flow.client.api.WorkflowsApi;
import com.kiwify.flow.client.auth.HttpBearerAuth;

ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://your-kiwiflow-host");
((HttpBearerAuth) client.getAuthentication("ApiKey")).setBearerToken(apiKey);

WorkflowsApi workflowsApi = new WorkflowsApi(client);
RunsApi runsApi = new RunsApi(client);
Node.js
import { Configuration, RunsApi, WorkflowsApi } from "kiwiflow";

const config = new Configuration({
  basePath: "https://your-kiwiflow-host",
  accessToken: apiKey,
});

const workflowsApi = new WorkflowsApi(config);
const runsApi = new RunsApi(config);
Python
import kiwiflow
from kiwiflow.api import runs_api, workflows_api

config = kiwiflow.Configuration(host="https://your-kiwiflow-host")
config.access_token = api_key

client = kiwiflow.ApiClient(config)
workflows = workflows_api.WorkflowsApi(client)
runs = runs_api.RunsApi(client)

List workflows#

.NET
var response = await workflowsApi.ListWorkflowsAsync();
foreach (var wf in response.Ok())
    Console.WriteLine($"{wf.WorkflowId} {wf.Name}");
Java
for (var wf : workflowsApi.listWorkflows()) {
    System.out.println(wf.getWorkflowId() + " " + wf.getName());
}
Node.js
for (const wf of await workflowsApi.listWorkflows()) {
  console.log(wf.workflowId, wf.name);
}
Python
for wf in workflows.list_workflows():
    print(wf.workflow_id, wf.name)

Run a workflow and wait for the result#

Start a run with its inputs, then poll the run until it is no longer Running. Do not use the /execute-stream endpoint from the SDKs; it is not supported there.

.NET
var started = (await workflowsApi.ExecuteWorkflowAsync(
    workflowId,
    new ExecuteRequest(new Dictionary<string, object?> { ["customerId"] = 42 }))).Ok()!;

var run = started;
while (run.Status == "Running")
{
    await Task.Delay(TimeSpan.FromSeconds(2));
    run = (await runsApi.GetRunAsync(started.RunId)).Ok()!;
}
Console.WriteLine($"{run.Status}: {run.OutputsJson}");
Java
import com.kiwify.flow.client.model.ExecuteRequest;
import com.kiwify.flow.client.model.RunDetail;
import java.util.Map;

RunDetail started = workflowsApi.executeWorkflow(
    workflowId, new ExecuteRequest().inputs(Map.of("customerId", 42)));

RunDetail run = started;
while ("Running".equals(run.getStatus())) {
    Thread.sleep(2000);
    run = runsApi.getRun(started.getRunId());
}
System.out.println(run.getStatus() + ": " + run.getOutputsJson());
Node.js
const started = await workflowsApi.executeWorkflow({
  workflowId,
  executeRequest: { inputs: { customerId: 42 } },
});

let run = started;
while (run.status === "Running") {
  await new Promise((resolve) => setTimeout(resolve, 2000));
  run = await runsApi.getRun({ runId: started.runId });
}
console.log(`${run.status}: ${run.outputsJson}`);
Python
import time

started = workflows.execute_workflow(
    workflow_id, kiwiflow.ExecuteRequest(inputs={"customerId": 42}))

run = started
while run.status == "Running":
    time.sleep(2)
    run = runs.get_run(started.run_id)
print(f"{run.status}: {run.outputs_json}")

inputsJson, outputsJson and logJson on the run are JSON documents carried as strings. A run that has to wait for an approval or an external task reports another status, so handle it in your own loop if your workflows use those activities.

The kiwi flow CLI#

The CLI is built on the .NET SDK and runs inside the Kiwi shell as kiwi flow <command>. login returns a durable API key directly, and the CLI caches a protected session token and an optional saved URL and key under ~/.kiwiflow/. See the CLI reference.