Intempt Docs
Developer DocsSDK

Java SDK

Read Intempt feature flags, experiments and personalizations by key from a JVM server.

Java SDK

Reads decisions. It does not send events.

Every other Intempt SDK on this list captures events; this one asks Intempt what to serve and nothing else. Its whole public surface is eight methods on IntemptClient, and all eight are flag reads. To send events from the JVM, post to the REST API.

It holds no per-user state: every call takes its identifier explicitly, so one client instance is shared across every request and every thread.

Not published yet. intempt-java has no tag, no GitHub release, and nothing under com.intempt on Maven Central. The coordinates below are what the POM declares, not something you can resolve today — until an artifact is published, build the repository yourself and install it into your local repository.

Requirements

Java17 or newer
Runtime dependenciesnone
Thread safetyone client, shared

No runtime dependencies is deliberate. This SDK is dropped into applications that already pin a JSON library, and a transitive version conflict is a bug that surfaces in someone else's release build rather than in ours. java.net.http plus a small reader cover what it needs.

Installation

<dependency>
  <groupId>com.intempt</groupId>
  <artifactId>intempt-java</artifactId>
  <version>0.1.0</version>
</dependency>

Setup

valuewhere it comes fromrequired
orgyour organization name in the console URLyes
projectyour project name in the console URLyes
sourceIdthe source you are sending asyes
apiKeya server key from the consoleyes
hostoverride the API hostno
timeoutper-request timeoutno
IntemptConfig config = IntemptConfig.builder()
    .org("acme")
    .project("web")
    .sourceId("42")
    .apiKey(System.getenv("INTEMPT_API_KEY"))
    .timeout(Duration.ofMillis(800))
    .build();

try (IntemptClient client = new IntemptClient(config)) {
    // ...
}

The evaluation endpoint requires a server credential. A public key holds users and accounts and nothing else, and the response describes how every experience in the project targets, so a public key is refused there.

Identity

FlagContext carries who is being evaluated. profileId is the anonymous or device identifier; passing the same value before and after someone signs in is what keeps their assignment stable across the transition.

FlagContext.ofUser("user-123");
FlagContext.ofProfile("device-abc");
FlagContext.of("user-123", "device-abc");

Feature flags

Read a flag by key. You never name a mode — Intempt resolves whether that key is an experiment, a personalization or a flag, so a key can change mode without your code changing.

FlagContext context = FlagContext.ofUser("user-123");

boolean on = client.boolVariation("new_checkout", context, false);
String copy = client.stringVariation("banner_copy", context, "Welcome");
Map<String, Object> all = client.allFlags(context);
CallReturns
variation(key, context, default)the value assigned for that key
variationDetail(key, context, default)a FlagDetail — see below
allFlags(context)every key assigned to this person, in one call

The default is required. It is what you receive on a network failure, a timeout, an unknown key or a malformed response — so an outage degrades to your existing behaviour instead of an exception. A flag lookup never throws for a service problem. It throws IllegalArgumentException only for a programming mistake: a blank key, or a missing default.

Typed helpers

boolVariation, stringVariation and numberVariation return the type already converted and fall back to the default if the served value is the wrong shape — so a flag configured as a string and read as a boolean gives your default, not true.

variationDetail

variationDetail returns a FlagDetail<T> with three accessors: value(), reason() and variant().

Only value() is meaningful today. The optimization/choose-api response carries name, group and body and no reason at all, so reason() resolves to OFF on every call, and variant() returns the selector group rather than the variant that was served. Branch on variation and measure holdouts in Intempt, where the exposure is recorded.

Initialization and shutdown

Evaluation is remote. There is no local rule engine and no flag store to poll, so bucketing can never disagree between your code and the platform.

waitForInitialization(timeoutMillis) returns immediately. It exists so porting from a polling SDK does not mean deleting the call. close() is present so the client works in try-with-resources and is a no-op today.

On this page