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

Fetch the latest SSE event for an execution. Use this to check the final state after triggering an execution.

public class ExecutionsExamples {
public static void followExecution() {
String executionId = "your-execution-id";
String tenant = "main";
var event = KestraClients.INSTANCE.executions()
.followExecution(executionId, tenant);
if (event != null) {
System.out.printf("Event: %s%n", event.getId());
if (event.getData() != null) {
System.out.printf("Status: %s%n", event.getData().getState());
}
}
}
}

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");
}
}

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?