For the complete documentation index, see llms.txt.
Skip to main content
Version: 8.10 (unreleased)

Quick Start (Zero-Config — Recommended)

Keep configuration out of application code. Let the factory read CAMUNDA_* variables from the environment (12-factor style). This makes rotation, secret management, and environment promotion safer and simpler.

using Camunda.Orchestration.Sdk;

// Zero-config construction: reads CAMUNDA_* from environment variables.
// If no configuration is present, defaults to Camunda 8 Run on localhost.
using var client = CamundaClient.Create();

var topology = await client.GetTopologyAsync();
Console.WriteLine($"Brokers: {topology.Brokers?.Count ?? 0}");

Typical environment (example):

CAMUNDA_REST_ADDRESS=https://cluster.example   # SDK appends /v2 automatically
CAMUNDA_AUTH_STRATEGY=OAUTH
CAMUNDA_CLIENT_ID=***
CAMUNDA_CLIENT_SECRET=***
CAMUNDA_OAUTH_URL=https://login.cloud.camunda.io/oauth/token
CAMUNDA_DEFAULT_TENANT_ID=<default> # optional: override default tenant

Why zero-config?

  • Separation of concerns: business code depends on an interface, not on secrets/constants wiring.
  • 12-Factor alignment: config lives in the environment → simpler promotion (dev → staging → prod).
  • Secret rotation: rotate credentials without a code change or redeploy.
  • Immutable start: single hydration pass prevents drift / mid-request mutations.
  • Test ergonomics: swap env vars per test without touching source; create multiple clients for multi-tenant tests.
  • Security review: fewer code paths handling secrets; scanners & vault tooling work at the boundary.
  • Deploy portability: same artifact runs everywhere; only the environment differs.
  • Cross-SDK consistency: identical variable names across JavaScript, C#, and Python SDKs.

Programmatic Overrides (Advanced)

Use only when you must supply or mutate configuration dynamically (e.g. multi-tenant routing, tests, ephemeral preview environments). Keys mirror their CAMUNDA_* env names:

using Camunda.Orchestration.Sdk;

using var client = CamundaClient.Create(new CamundaOptions
{
Config = new Dictionary<string, string>
{
["CAMUNDA_REST_ADDRESS"] = "https://my-cluster.camunda.io",
["CAMUNDA_AUTH_STRATEGY"] = "OAUTH",
["CAMUNDA_CLIENT_ID"] = "my-client-id",
["CAMUNDA_CLIENT_SECRET"] = "my-secret",
["CAMUNDA_OAUTH_URL"] = "https://login.cloud.camunda.io/oauth/token",
["CAMUNDA_TOKEN_AUDIENCE"] = "zeebe.camunda.io",
},
});

Configuration via appsettings.json

The SDK can read configuration from any IConfiguration source (appsettings.json, user secrets, Azure Key Vault, etc.) using idiomatic .NET PascalCase section keys:

{
"Camunda": {
"RestAddress": "https://cluster.example.com",
"Auth": {
"Strategy": "OAUTH",
"ClientId": "my-client-id",
"ClientSecret": "my-secret"
},
"OAuth": {
"Url": "https://login.cloud.camunda.io/oauth/token"
},
"Backpressure": {
"Profile": "CONSERVATIVE"
}
}
}

Pass the section to the client:

using Camunda.Orchestration.Sdk;

var builder = WebApplication.CreateBuilder(args);

using var client = CamundaClient.Create(new CamundaOptions
{
Configuration = builder.Configuration.GetSection("Camunda"),
});

Precedence (highest wins): Config dictionary > IConfiguration section > environment variables > defaults.

This means you can set secrets via environment variables (or a vault) and non-sensitive settings via appsettings.json — they layer naturally:

// appsettings.json — non-sensitive, checked into source control
{
"Camunda": {
"RestAddress": "https://cluster.example.com",
"Backpressure": { "Profile": "CONSERVATIVE" }
}
}
# Secrets injected via environment (vault, CI, container orchestrator)
CAMUNDA_CLIENT_ID=***
CAMUNDA_CLIENT_SECRET=***
CAMUNDA_OAUTH_URL=https://login.cloud.camunda.io/oauth/token
appsettings.json key reference
appsettings.json keyMaps to env var
RestAddressCAMUNDA_REST_ADDRESS
TokenAudienceCAMUNDA_TOKEN_AUDIENCE
DefaultTenantIdCAMUNDA_DEFAULT_TENANT_ID
LogLevelCAMUNDA_SDK_LOG_LEVEL
ValidationCAMUNDA_SDK_VALIDATION
Auth:StrategyCAMUNDA_AUTH_STRATEGY
Auth:ClientIdCAMUNDA_CLIENT_ID
Auth:ClientSecretCAMUNDA_CLIENT_SECRET
Auth:BasicUsernameCAMUNDA_BASIC_AUTH_USERNAME
Auth:BasicPasswordCAMUNDA_BASIC_AUTH_PASSWORD
OAuth:UrlCAMUNDA_OAUTH_URL
OAuth:ClientIdCAMUNDA_CLIENT_ID
OAuth:ClientSecretCAMUNDA_CLIENT_SECRET
OAuth:GrantTypeCAMUNDA_OAUTH_GRANT_TYPE
OAuth:ScopeCAMUNDA_OAUTH_SCOPE
OAuth:TimeoutMsCAMUNDA_OAUTH_TIMEOUT_MS
OAuth:RetryMaxCAMUNDA_OAUTH_RETRY_MAX
OAuth:RetryBaseDelayMsCAMUNDA_OAUTH_RETRY_BASE_DELAY_MS
HttpRetry:MaxAttemptsCAMUNDA_SDK_HTTP_RETRY_MAX_ATTEMPTS
HttpRetry:BaseDelayMsCAMUNDA_SDK_HTTP_RETRY_BASE_DELAY_MS
HttpRetry:MaxDelayMsCAMUNDA_SDK_HTTP_RETRY_MAX_DELAY_MS
Backpressure:ProfileCAMUNDA_SDK_BACKPRESSURE_PROFILE
Backpressure:InitialMaxCAMUNDA_SDK_BACKPRESSURE_INITIAL_MAX
Backpressure:SoftFactorCAMUNDA_SDK_BACKPRESSURE_SOFT_FACTOR
Backpressure:SevereFactorCAMUNDA_SDK_BACKPRESSURE_SEVERE_FACTOR
Backpressure:RecoveryIntervalMsCAMUNDA_SDK_BACKPRESSURE_RECOVERY_INTERVAL_MS
Backpressure:RecoveryStepCAMUNDA_SDK_BACKPRESSURE_RECOVERY_STEP
Backpressure:DecayQuietMsCAMUNDA_SDK_BACKPRESSURE_DECAY_QUIET_MS
Backpressure:FloorCAMUNDA_SDK_BACKPRESSURE_FLOOR
Backpressure:SevereThresholdCAMUNDA_SDK_BACKPRESSURE_SEVERE_THRESHOLD
Eventual:PollDefaultMsCAMUNDA_SDK_EVENTUAL_POLL_DEFAULT_MS

Dependency Injection (AddCamundaClient)

For ASP.NET Core and other DI-based applications, use the AddCamundaClient() extension method on IServiceCollection. The client is registered as a singleton and automatically picks up ILoggerFactory from the container.

Zero-config (environment variables only):

using Camunda.Orchestration.Sdk;

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCamundaClient();

With appsettings.json:

using Camunda.Orchestration.Sdk;

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCamundaClient(builder.Configuration.GetSection("Camunda"));

With options callback (full control):

using Camunda.Orchestration.Sdk;

builder.Services.AddCamundaClient(options =>
{
options.Configuration = builder.Configuration.GetSection("Camunda");
// or: options.Config = new Dictionary<string, string> { ... };
});

Inject the client anywhere via constructor injection:

public class OrderController(CamundaClient camunda) : ControllerBase
{
[HttpPost]
public async Task<IActionResult> StartProcess()
{
var result = await camunda.CreateProcessInstanceAsync(
new ProcessInstanceCreationInstructionById
{
ProcessDefinitionId = ProcessDefinitionId.AssumeExists("order-process"),
});
return Ok(result);
}
}

Custom HttpClient

using Camunda.Orchestration.Sdk;

var httpClient = new HttpClient { BaseAddress = new Uri("https://my-cluster/v2/") };
using var client = CamundaClient.Create(new CamundaOptions
{
HttpClient = httpClient,
});