Set Up the Kestra Java SDK and Build Workflows Programmatically

For the complete documentation index, see llms.txt. For a full content snapshot, see llms-full.txt. Append .md to any kestra.io/docs/* URL for plain Markdown.

Use the Kestra Java SDK to interact with the Kestra API from Java applications.

Install the Java SDK

Choose the installation method that matches your build tool.

Maven

Add this dependency to your pom.xml:

<dependency>
<groupId>io.kestra</groupId>
<artifactId>kestra-api-client</artifactId>
<version>1.0.0</version>
<scope>compile</scope>
</dependency>

Gradle

Add this dependency to your build.gradle:

implementation "io.kestra:kestra-api-client:1.0.0"

Configure the client

Initialize KestraClient once using the builder, then reuse it across your application. Read credentials from environment variables rather than hardcoding them.

import io.kestra.sdk.KestraClient;
public final class KestraClients {
private KestraClients() {}
public static final KestraClient INSTANCE = KestraClient.builder()
.url(System.getenv().getOrDefault("KESTRA_URL", "http://localhost:8080"))
.basicAuth(
System.getenv().getOrDefault("KESTRA_USER", "root@root.com"),
System.getenv().getOrDefault("KESTRA_PASS", "Root!1234")
)
// .tokenAuth(System.getenv("KESTRA_TOKEN")) // use instead for bearer auth
.build();
}

Create a flow

Send the flow definition as a YAML string. This matches what you would define in the UI.

import io.kestra.sdk.KestraClient;
public class FlowsExamples {
public static void createFlow() {
String tenant = "main";
String body = """
id: my_flow
namespace: my_namespace
tasks:
- id: hello
type: io.kestra.plugin.core.log.Log
message: Hello World!
""";
KestraClients.INSTANCE.flows().createFlow(tenant, body);
System.out.println("Flow created: my_namespace/my_flow");
}
}

Update a flow

Send the full YAML — including the same id and namespace — to replace an existing flow.

public class FlowsExamples {
public static void updateFlow() {
String id = "my_flow";
String namespace = "my_namespace";
String tenant = "main";
String body = """
id: my_flow
namespace: my_namespace
tasks:
- id: hello
type: io.kestra.plugin.core.log.Log
message: Updated message!
""";
KestraClients.INSTANCE.flows().updateFlow(id, namespace, tenant, body);
System.out.println("Flow updated: my_namespace/my_flow");
}
}

Delete a flow

Remove a flow by its namespace, id, and tenant.

public class FlowsExamples {
public static void deleteFlow() {
String namespace = "my_namespace";
String id = "my_flow";
String tenant = "main";
KestraClients.INSTANCE.flows().deleteFlow(namespace, id, tenant);
System.out.println("Flow deleted: my_namespace/my_flow");
}
}

Execute a flow

Trigger an execution and optionally pass labels or scheduling parameters.

import java.util.List;
import java.time.OffsetDateTime;
import io.kestra.sdk.ApiException;
import io.kestra.sdk.model.ExecutionKind;
public class ExecutionsExamples {
public static void createExecution() {
String namespace = "my_namespace";
String id = "my_flow";
String tenant = "main";
Boolean wait = false;
try {
KestraClients.INSTANCE.executions()
.createExecution(
namespace, id, wait, tenant,
List.of("team:platform"), // labels
null, // revision (null = latest)
(OffsetDateTime) null, // scheduleDate
null, // breakpoint task ID
ExecutionKind.NORMAL
);
} catch (ApiException e) {
if (e.getCode() != 0) throw e; // code 0 = deserialization-only; execution ran normally
}
System.out.println("Execution triggered");
}
}

Delete an execution

Delete an execution and optionally purge its logs, metrics, and storage.

public class ExecutionsExamples {
public static void deleteExecution() {
String executionId = "your-execution-id";
String tenant = "main";
KestraClients.INSTANCE.executions()
.deleteExecution(executionId, true, true, true, tenant);
System.out.println("Execution deleted");
}
}

Follow an execution

followExecution returns a reactive Flux<Execution> that streams state updates as the execution progresses. Each emission is an Execution object — skip entries where getState() is null (keepalive frames emitted by the server before the first real update).

public class ExecutionsExamples {
public static void followExecution() {
String executionId = "your-execution-id";
String tenant = "main";
KestraClients.INSTANCE.executions()
.followExecution(executionId, tenant)
.filter(execution -> execution.getState() != null) // skip keepalive frames
.doOnNext(execution -> System.out.printf("[%s] %s%n",
execution.getId(), execution.getState().getCurrent()))
.blockLast(); // blocks until the execution stream ends
}
}

KV Store

The KV Store lets you read and write key-value pairs scoped to a namespace.

List keys

public class KVExamples {
public static void listKeys() {
String namespace = "my_namespace";
String tenant = "main";
var keys = KestraClients.INSTANCE.kv().listKeys(namespace, tenant);
keys.forEach(entry -> System.out.println("Key: " + entry.getKey()));
}
}

Get a value

public class KVExamples {
public static void getKeyValue() {
String namespace = "my_namespace";
String tenant = "main";
var result = KestraClients.INSTANCE.kv()
.getKeyValue(namespace, "my_key", tenant);
System.out.println("Value: " + result.getValue());
}
}

Set a value

public class KVExamples {
public static void setKeyValue() {
String namespace = "my_namespace";
String tenant = "main";
KestraClients.INSTANCE.kv()
.setKeyValue(namespace, "my_key", tenant, "my_value");
System.out.println("Key set");
}
}

Delete a key

public class KVExamples {
public static void deleteKey() {
String namespace = "my_namespace";
String tenant = "main";
KestraClients.INSTANCE.kv().deleteKeyValue(namespace, "my_key", tenant);
System.out.println("Key deleted");
}
}

Read execution logs

Fetch or stream logs for an execution.

List logs

import io.kestra.sdk.model.Level;
public class LogsExamples {
public static void listLogs() {
String executionId = "your-execution-id";
String tenant = "main";
var logs = KestraClients.INSTANCE.logs()
.listLogsFromExecution(executionId, tenant,
null, // minLevel (null = all levels)
null, // taskRunId
null, // taskId
null // attempt
);
logs.forEach(log ->
System.out.printf("[%s] %s%n", log.getLevel(), log.getMessage()));
}
}

Stream logs live

import io.kestra.sdk.model.Level;
public class LogsExamples {
public static void followLogs() {
String executionId = "your-execution-id";
String tenant = "main";
var event = KestraClients.INSTANCE.logs()
.followLogsFromExecution(executionId, tenant, null);
if (event != null && event.getData() != null) {
System.out.printf("[%s] %s%n",
event.getData().getLevel(), event.getData().getMessage());
}
}
}

Manage triggers

Search, enable or disable, unlock, and restart triggers for flows.

Search triggers

public class TriggersExamples {
public static void searchTriggers() {
String tenant = "main";
var result = KestraClients.INSTANCE.triggers()
.searchTriggers(1, 50, tenant,
null, // sort
null, // filters
null, // query string
"my_namespace", // namespace filter
null, // workerId
null // flowId
);
result.getResults().forEach(t -> {
var ctx = t.getTriggerContext();
System.out.printf("%s: disabled=%s%n",
ctx.getTriggerId(), ctx.getDisabled());
});
}
}

Disable or enable a trigger

import io.kestra.sdk.model.TriggerControllerSetDisabledRequest;
import io.kestra.sdk.model.Trigger;
public class TriggersExamples {
public static void disableTrigger() {
String tenant = "main";
var request = new TriggerControllerSetDisabledRequest()
.addTriggersItem(new Trigger()
.namespace("my_namespace")
.flowId("my_flow")
.triggerId("my_schedule"))
.disabled(true); // pass false to re-enable
KestraClients.INSTANCE.triggers()
.disabledTriggersByIds(tenant, request);
System.out.println("Trigger disabled");
}
}

Unlock a trigger

Use unlockTrigger to unlock a trigger that is stuck in a locked state.

public class TriggersExamples {
public static void unlockTrigger() {
String tenant = "main";
KestraClients.INSTANCE.triggers()
.unlockTrigger("my_namespace", "my_flow", "my_schedule", tenant);
System.out.println("Trigger unlocked");
}
}

Restart a trigger

public class TriggersExamples {
public static void restartTrigger() {
String tenant = "main";
KestraClients.INSTANCE.triggers()
.restartTrigger("my_namespace", "my_flow", "my_schedule", tenant);
System.out.println("Trigger restarted");
}
}

Dashboards

Create, search, and delete dashboards.

Create a dashboard

public class DashboardsExamples {
public static void createDashboard() {
String tenant = "main";
String body = """
id: my_dashboard
title: My Dashboard
""";
var dashboard = KestraClients.INSTANCE.dashboards().createDashboard(tenant, body);
System.out.println("Dashboard created: " + dashboard.getId());
}
}

Search dashboards

public class DashboardsExamples {
public static void searchDashboards() {
String tenant = "main";
var result = KestraClients.INSTANCE.dashboards().searchDashboards(tenant, null, null, null, null);
result.getResults().forEach(d -> System.out.println(d.getId()));
}
}

Delete a dashboard

public class DashboardsExamples {
public static void deleteDashboard() {
String tenant = "main";
KestraClients.INSTANCE.dashboards().deleteDashboard("my_dashboard_id", tenant);
System.out.println("Dashboard deleted");
}
}

Namespace files

List, read, and delete files stored in a namespace.

List files

public class FilesExamples {
public static void listFiles() {
var files = KestraClients.INSTANCE.files()
.listNamespaceDirectoryFiles("my_namespace", "main", "/");
files.forEach(f -> System.out.println(f.getFileName()));
}
}

Read file content

import java.io.File;
public class FilesExamples {
public static void readFile() {
String tenant = "main";
File content = KestraClients.INSTANCE.files()
.fileContent("my_namespace", "/scripts/main.py", tenant, null);
System.out.println("Downloaded to: " + content.getAbsolutePath());
}
}

Delete a file

public class FilesExamples {
public static void deleteFile() {
String tenant = "main";
KestraClients.INSTANCE.files()
.deleteFileDirectory("my_namespace", "/scripts/main.py", tenant);
System.out.println("File deleted");
}
}

Test suites

Create, run, and fetch results for unit test suites.

Create a test suite

public class TestSuitesExamples {
public static void createTestSuite() {
String tenant = "main";
String body = """
id: my_tests
namespace: my_namespace
flows:
- flowId: my_flow
""";
var suite = KestraClients.INSTANCE.testSuites().createTestSuite(tenant, body);
System.out.println("Test suite created: " + suite.getId());
}
}

Run a test suite

public class TestSuitesExamples {
public static void runTestSuite() {
String tenant = "main";
var result = KestraClients.INSTANCE.testSuites()
.runTestSuite("my_namespace", "my_tests", tenant, null);
System.out.println("State: " + result.getState());
}
}

Get test results

public class TestSuitesExamples {
public static void getTestResult() {
String tenant = "main";
var result = KestraClients.INSTANCE.testSuites().testResult("run-id", tenant);
System.out.println("State: " + result.getState());
}
}

Apps

Create, enable, disable, and delete apps.

Create an app

public class AppsExamples {
public static void createApp() {
String tenant = "main";
String body = """
id: my_app
title: My App
""";
var app = KestraClients.INSTANCE.apps().createApp(tenant, body);
System.out.println("App created: " + app.getUid());
}
}

Enable or disable an app

public class AppsExamples {
public static void enableApp() {
String tenant = "main";
KestraClients.INSTANCE.apps().enableApp("app-uid", tenant);
System.out.println("App enabled");
}
public static void disableApp() {
String tenant = "main";
KestraClients.INSTANCE.apps().disableApp("app-uid", tenant);
System.out.println("App disabled");
}
}

Delete an app

public class AppsExamples {
public static void deleteApp() {
String tenant = "main";
KestraClients.INSTANCE.apps().deleteApp("app-uid", tenant);
System.out.println("App deleted");
}
}

Best practices

  • Reuse your client: construct one KestraClient per application (singleton or DI).
  • Externalize credentials: read URL and auth from environment variables or your config system.
  • Keep flow YAML as code: store YAML strings or templates under version control for traceability.
  • Use labels for governance, search, and routing across executions.

Was this page helpful?