Java SDK

A typed client for the Emnet verification API with no framework dependencies — it drops into a Spring, Quarkus or plain-Java service without a dependency fight.

Install

The SDK is distributed with your early-access key, together with its install instructions. Request a key by writing to sales@emnetid.com.

What it pulls in

Jackson and SLF4J. That is all. HTTP is the JDK’s own java.net.http.HttpClient, and the SDK deliberately does not inherit any Spring BOM — so it can never drag a framework version into your build. Requires Java 21 or later.

Create a client

EmnetClient is immutable and thread-safe. Create one per application and reuse it — creating one per request wastes connections.

Simple
EmnetClient emnet = new EmnetClient(
    System.getenv("EMNET_BASE_URL"),
    System.getenv("EMNET_API_KEY"));
With the builder
EmnetClient emnet = EmnetClient.builder()
    .baseUrl(System.getenv("EMNET_BASE_URL"))
    .apiKey(System.getenv("EMNET_API_KEY"))
    .connectTimeout(Duration.ofSeconds(10))
    .requestTimeout(Duration.ofSeconds(30))
    .build();

Builder options

OptionDefaultNotes
baseUrl—Required. Your base URL is issued with your early-access key; read it from EMNET_BASE_URL.
apiKey—Required. Load from the environment or a secret manager.
connectTimeout10sTCP connect timeout.
requestTimeout30sPer-request timeout. Raise it only if your network genuinely needs it.
httpClientJDK defaultSupply your own HttpClient for proxying or custom TLS.
objectMapperPreconfiguredSupply your own Jackson mapper if you must; the default already handles dates and unknown fields.

Spring configuration

EmnetConfig.java
@Configuration
class EmnetConfig {

    @Bean
    EmnetClient emnetClient(
            @Value("${emnet.base-url}") String baseUrl,
            @Value("${emnet.api-key}") String apiKey) {
        return EmnetClient.builder()
                .baseUrl(baseUrl)
                .apiKey(apiKey)
                .build();
    }
}
application.yml
emnet:
  base-url: ${EMNET_BASE_URL}   # no default — issued with your key
  api-key: ${EMNET_API_KEY}     # no default — fail fast if it is missing

Methods

startPersonVerification()

java
AuthorizeUrlResponse start = emnet.startPersonVerification();

start.authorizeUrl();   // redirect the user here
start.state();          // store this against their session

completePersonVerification(code, state)

java
VerifiedIdentity identity = emnet.completePersonVerification(code, state);

// or with the request object
VerifiedIdentity identity = emnet.completePersonVerification(
        new FaydaCallbackRequest(code, state));

Requires a secret key. See Claims & identity keys for what the result contains.

getSession(sessionId)

java
VerificationSessionView view = emnet.getSession(4711L);

view.status();          // "COMPLETED"
view.assuranceLevel();
view.completedAt();

Error handling

ExceptionWhenCarries
EmnetApiExceptionThe API returned a non-2xx statusstatus() and body()
EmnetExceptionTransport failure, timeout or a response that could not be parsedMessage and cause

EmnetApiException extends EmnetException, so catching the latter catches both.

Handling both
try {
    VerifiedIdentity identity = emnet.completePersonVerification(code, state);
    users.markVerified(userId, identity);

} catch (EmnetApiException e) {
    switch (e.status()) {
        case 400 -> return badRequest("This verification link has expired. Please start again.");
        case 403 -> throw new IllegalStateException("Publishable key used server-side — use a secret key");
        case 429 -> return retryLater();          // honour Retry-After
        case 503 -> return providerUnavailable();
        default  -> {
            log.warn("Emnet returned {}", e.status());   // status only, never the body
            return genericFailure();
        }
    }

} catch (EmnetException e) {
    log.warn("Emnet call failed: {}", e.getMessage());
    return genericFailure();
}
Never log the exception body

body() exists for debugging in a controlled environment. Logging it risks writing personal data into a log aggregator that a much wider group can read. Log the status; look at the body only when you are actively debugging.

What the SDK will never do

  • Log your API key, a national identifier or a released claim — at any log level.
  • Retry automatically. Retry policy is yours, because only you know whether the operation is safe to repeat.
  • Cache verification results. Store what you need in your own database.
  • Pull in a web framework, a DI container or a logging implementation.

Testing

Point a test key at the API in your integration tests — test verifications are free and unlimited, so there is no reason to mock the transport. For unit tests, inject a stub HttpClient through the builder.

Integration test
@Test
void completesAVerification() {
    EmnetClient emnet = EmnetClient.builder()
            .baseUrl(System.getenv("EMNET_BASE_URL"))
            .apiKey(System.getenv("EMNET_TEST_API_KEY"))   // sk_test_...
            .build();

    AuthorizeUrlResponse start = emnet.startPersonVerification();

    assertThat(start.authorizeUrl()).startsWith("https://");
    assertThat(start.state()).isNotBlank();
}

Other languages

Java is the only officially supported SDK today. Every endpoint is plain JSON over HTTPS, so any language integrates directly — see the API reference, or generate a client from the OpenAPI document shipped with the SDK.