> ## Documentation Index
> Fetch the complete documentation index at: https://docs.didit.me/llms.txt
> Use this file to discover all available pages before exploring further.

# Java and Kotlin SDK for KYC, AML and Transactions

> Quickstart for the official Didit Java and Kotlin SDK: typed builders for the server APIs, sync and async calls, webhook verification and token checks.

The official Didit library for Java and Kotlin. It needs Java 11 or later and depends only on `java.net.http`, Jackson and the JSpecify nullness annotations. Every method has an `...Async` variant that returns a `CompletableFuture`. See the [server SDKs overview](https://docs.didit.me/integration/server-sdks/overview.md) for what every SDK shares.

## Install

```kotlin Gradle theme={null}
implementation("me.didit:didit-java:1.0.1")
```

```xml Maven theme={null}
<dependency>
  <groupId>me.didit</groupId>
  <artifactId>didit-java</artifactId>
  <version>1.0.1</version>
</dependency>
```

The artifact is [`me.didit:didit-java` on Maven Central](https://central.sonatype.com/artifact/me.didit/didit-java). Its source and changelog are in [didit-protocol/sdk-java](https://github.com/didit-protocol/sdk-java) on GitHub.

## Configure the client

`new Didit()` reads `DIDIT_API_KEY` from the environment. Use the builder to override it, or to set the organization and application ids that application-scoped calls (cases, networks, regulatory reports) need.

```java theme={null}
import java.time.Duration;
import me.didit.Didit;
import me.didit.core.RequestOptions;
import me.didit.types.SessionsRetrieveDecisionParams;

Didit client = Didit.builder()
        .apiKey(System.getenv("DIDIT_API_KEY"))
        .organizationId(System.getenv("DIDIT_ORGANIZATION_ID"))
        .applicationId(System.getenv("DIDIT_APPLICATION_ID"))
        .timeout(Duration.ofSeconds(30))
        .maxRetries(2)
        .build();

// Options for a single call.
var decision = client.sessions().retrieveDecision("11111111-2222-3333-4444-555555555555",
        SessionsRetrieveDecisionParams.builder().build(),
        RequestOptions.builder().timeout(Duration.ofSeconds(5)).build());
System.out.println(decision.status().orElse(null));
```

Request types are builders whose `build()` checks the required fields. Optional response fields are `Optional` values; in Kotlin, read them with `.getOrNull()`. The snippets on this page and on each [API reference](https://docs.didit.me/api-reference/overview.md) page are the body of a method, with the imports they need above them.

## Create a session

Create a [verification session](https://docs.didit.me/sessions-api/create-session.md) for a workflow and send your user to its URL.

```java theme={null}
import me.didit.Didit;
import me.didit.types.SessionsCreateParams;

Didit client = new Didit();

var session = client.sessions().create(SessionsCreateParams.builder()
        .workflowId("11111111-2222-3333-4444-555555555555")
        .vendorData("user-123")
        .callback("https://example.com/verification/done")
        .build());
System.out.println(session.url());
```

## Read the decision

When the user finishes (or when the webhook arrives), [read the decision](https://docs.didit.me/sessions-api/retrieve-session.md). Every feature result is a list with one entry per workflow node.

```java theme={null}
import java.util.List;
import me.didit.Didit;

Didit client = new Didit();

var decision = client.sessions().retrieveDecision("11111111-2222-3333-4444-555555555555");
decision.status().ifPresent(status -> System.out.println(status));
for (var verification : decision.idVerifications().orElse(List.of())) {
    System.out.println(verification.status().orElse(null));
}
```

## Verify a webhook

Pass the raw body, exactly as received, and the request headers. `Webhooks.verify` throws `WebhookVerificationException` for anything that is not a valid, fresh delivery, and returns a typed event otherwise.

```java theme={null}
import java.util.Map;
import me.didit.errors.WebhookVerificationException;
import me.didit.webhooks.SessionStatusUpdatedEvent;
import me.didit.webhooks.WebhookEvent;
import me.didit.webhooks.Webhooks;

public class DiditWebhookHandler {
    private final String secret = System.getenv("DIDIT_WEBHOOK_SECRET");

    public int handle(byte[] rawBody, Map<String, String> headers) {
        WebhookEvent event;
        try {
            event = Webhooks.verify(rawBody, headers, secret);
        } catch (WebhookVerificationException e) {
            System.out.println("rejected: " + e.reason());
            return 400;
        }
        if (event instanceof SessionStatusUpdatedEvent) {
            SessionStatusUpdatedEvent updated = (SessionStatusUpdatedEvent) event;
            System.out.println(updated.sessionId().orElse("") + " " + updated.status().orElse(""));
        }
        return 200;
    }
}
```

In Spring Boot, take the body as `@RequestBody byte[] body` and the headers as `@RequestHeader Map<String, String> headers`. To accept two secrets while you rotate one, pass `VerifyOptions`. See [Webhooks](https://docs.didit.me/integration/webhooks.md) for the events and the signature scheme.

## Screen a transaction

Submit a payment, withdrawal or crypto transfer to [transaction monitoring](https://docs.didit.me/transaction-monitoring/overview.md); the response carries its status and risk score.

```java theme={null}
import me.didit.Didit;
import me.didit.types.TransactionsCreateParams;

Didit client = new Didit();

var transaction = client.transactions().create(TransactionsCreateParams.builder()
        .transactionId("txn-1001")
        .transactionCategory(TransactionsCreateParams.TransactionCategory.of("finance"))
        .transactionDetails(TransactionsCreateParams.TransactionDetails.builder()
                .direction(TransactionsCreateParams.TransactionDetails.Direction.of("outbound"))
                .amount(1500.0)
                .currency("EUR")
                .build())
        .subject(TransactionsCreateParams.Subject.builder()
                .entityType("individual")
                .vendorData("user-123")
                .fullName("Maria Garcia")
                .build())
        .build());
System.out.println(transaction.status().orElse(null) + " " + transaction.score().orElse(null));
```

## Verify Authentication tokens

`Authentication` checks the access tokens your [Authentication](https://docs.didit.me/authentication/overview.md) issuer signs, in your backend, without calling Didit for each request. It also exchanges codes, refreshes tokens, checks and revokes sessions, and runs step-ups.

> [!NOTE]
>
> Token verification makes the checks in [Verify a token on your server](https://docs.didit.me/authentication/tokens-and-jwks.md#verify-a-token-on-your-server), against your application's issuer and signing keys.

```java theme={null}
import me.didit.authentication.AccessTokenClaims;
import me.didit.authentication.Authentication;
import me.didit.errors.TokenVerificationException;

public class CurrentUser {
    // The publishable key (pk_live_... or pk_test_...) carries your issuer URL.
    private final Authentication auth = Authentication.builder()
            .publishableKey("pk_live_...")
            .clientId("your-application-id")
            .build();

    public String subject(String accessToken) {
        try {
            AccessTokenClaims claims = auth.verifyAccessToken(accessToken);
            return claims.subject();
        } catch (TokenVerificationException e) {
            System.out.println("rejected: " + e.reason());
            return null;
        }
    }
}
```

## Errors

Every exception extends the unchecked `DiditException`.

```java theme={null}
import me.didit.Didit;
import me.didit.errors.ApiStatusException;
import me.didit.errors.NotFoundException;

Didit client = new Didit();

try {
    client.sessions().retrieveDecision("11111111-2222-3333-4444-555555555555");
} catch (NotFoundException e) {
    System.out.println("no such session");
} catch (ApiStatusException e) {
    System.out.println(e.statusCode() + " " + e.requestId().orElse(""));
}
```

## Lists and files

```java theme={null}
import java.nio.file.Path;
import me.didit.Didit;
import me.didit.types.IdVerificationVerifyParams;
import me.didit.types.SessionsListParams;

Didit client = new Didit();

// Lists page through every result.
for (var session : client.sessions().list(SessionsListParams.builder().status("Approved").build())) {
    System.out.println(session);
}

// Uploads take a Path or a FileUpload (bytes or a stream).
var result = client.idVerification().verify(IdVerificationVerifyParams.builder()
        .frontImage(Path.of("id-front.jpg"))
        .backImage(Path.of("id-back.jpg"))
        .build());
System.out.println(result);
```

Server endpoint pages of the [API reference](https://docs.didit.me/api-reference/overview.md) have a Java sample for their operation, except for the endpoints and fields that no 1.0.1 release has yet, named in the [overview](https://docs.didit.me/integration/server-sdks/overview.md).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.