> This page is for version 2024-10-01 (default).
> For other versions, use one of these documentation indexes:
> - 2024-10-01 (default): https://docs.getkard.com/2024-10-01/llms.txt
> - Legacy: https://docs.getkard.com/legacy/llms.txt

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.getkard.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.getkard.com/_mcp/server.

# Getting Started

This guide walks you through installing the [**Kard Java SDK**](https://github.com/KardFinancial/kard-java-sdk/), authenticating with the Kard API, and making your first request.

## Prerequisites
- **Java 8+**
- **`KARD_CLIENT_ID` and `KARD_CLIENT_SECRET`**
- **Build tool:** Maven or Gradle

## Install the SDK

**Gradle**

Add the dependency in your `build.gradle` file:

```groovy
dependencies {
    implementation 'com.getkard:kard-financial-sdk'
}
```

**Maven**

Add the dependency in your `pom.xml` file:

```xml
<dependency>
    <groupId>com.getkard</groupId>
    <artifactId>kard-financial-sdk</artifactId>
    <version>1.5.1</version>
</dependency>
```

## Create a Client

Import and instantiate the `KardApiClient` using your credentials.

This SDK supports two authentication methods:

**OAuth Client Credentials**
```java
import com.kard.api.KardApiClient;

KardApiClient client = KardApiClient
    .withCredentials("YOUR_CLIENT_ID", "YOUR_CLIENT_SECRET")
    .build();
```

**Bearer Token Authentication**
```java
import com.kard.api.KardApiClient;

KardApiClient client = KardApiClient.builder()
    .token("your-access-token")
    .url("https://api.getkard.com")
    .build();
```

The client automatically handles **authentication, retries, and timeouts.**

## Environments

This SDK allows you to configure different environments for API requests.

```java
import com.kard.api.KardApiClient;
import com.kard.api.core.Environment;

KardApiClient client = KardApiClient.builder()
    .environment(Environment.Production)
    .build();
```

## Base URL

You can set a custom base URL when constructing the client.

```java
import com.kard.api.KardApiClient;

KardApiClient client = KardApiClient.builder()
    .url("https://example.com")
    .build();
```

## Make Your First API Calls

**1.** [Creating a User](https://docs.getkard.com/api/users/create):

```java
import com.kard.api.KardApiClient;
import com.kard.api.resources.commons.types.EnrolledRewardsType;
import com.kard.api.resources.users.types.CreateUsersObject;
import com.kard.api.resources.users.types.UserRequestAttributes;
import com.kard.api.resources.users.types.UserRequestData;
import com.kard.api.resources.users.types.UserRequestDataUnion;
import java.util.Arrays;

KardApiClient client = KardApiClient
    .withCredentials("YOUR_CLIENT_ID", "YOUR_CLIENT_SECRET")
    .build();

client.users().create(
    "organization-123",
    CreateUsersObject.builder()
        .data(Arrays.asList(
            UserRequestDataUnion.user(
                UserRequestData.builder()
                    .id("1234567890")
                    .attributes(
                        UserRequestAttributes.builder()
                            .zipCode("11238")
                            .enrolledRewards(
                                Arrays.asList(EnrolledRewardsType.CARDLINKED)
                            )
                            .build()
                    )
                    .build()
            )
        ))
        .build()
);
```

To enhance offer targeting and attribution, you can include a **hashed email (HEM)** when creating users. The SDK includes a built-in `HEM.generateHEM` utility that normalizes and hashes email addresses:

```java
import com.kard.api.KardApiClient;
import com.kard.api.resources.commons.types.EnrolledRewardsType;
import com.kard.api.resources.users.types.CreateUsersObject;
import com.kard.api.resources.users.types.UserRequestAttributes;
import com.kard.api.resources.users.types.UserRequestData;
import com.kard.api.resources.users.types.UserRequestDataUnion;
import com.kard.hem.HEM;
import java.util.Arrays;

KardApiClient client = KardApiClient
    .withCredentials("YOUR_CLIENT_ID", "YOUR_CLIENT_SECRET")
    .build();

String hashedEmail = HEM.generateHEM("Jane.Doe+work@gmail.com");

client.users().create(
    "organization-123",
    CreateUsersObject.builder()
        .data(Arrays.asList(
            UserRequestDataUnion.user(
                UserRequestData.builder()
                    .id("1234567890")
                    .attributes(
                        UserRequestAttributes.builder()
                            .enrolledRewards(
                                Arrays.asList(EnrolledRewardsType.CARDLINKED)
                            )
                            .hashedEmail(hashedEmail)
                            .build()
                    )
                    .build()
            )
        ))
        .build()
);
```

The function normalizes the email before hashing (removes whitespace, lowercases, and handles Gmail-specific rules like dot and `+` suffix removal). It throws an `IllegalArgumentException` for invalid inputs.

**2.** [Fetching Offers for User with Extended API](https://docs.getkard.com/api/rewards/offers):

```java
import com.kard.api.KardApiClient;
import com.kard.api.resources.users.rewards.types.ComponentType;
import java.util.Arrays;

KardApiClient client = KardApiClient
    .withCredentials("YOUR_CLIENT_ID", "YOUR_CLIENT_SECRET")
    .build();

client.users().rewards().offers(
    "organization-123",
    "1234567890",
    GetOffersByUserRequest.builder()
        .pageSize(1)
        .filterIsTargeted(true)
        .sort("-startDate")
        .supportedComponents(Arrays.asList(
            ComponentType.SHORT_DESCRIPTION,
            ComponentType.LONG_DESCRIPTION,
            ComponentType.CTA,
            ComponentType.TAGS,
            ComponentType.DETAIL_TAGS,
            ComponentType.BASE_REWARD
        ))
        .build()
);
```

**3.** [Submitting Transaction for User](https://docs.getkard.com/api/transactions/create):

```java
import com.kard.api.KardApiClient;
import com.kard.api.resources.transactions.types.*;
import java.util.Arrays;

KardApiClient client = KardApiClient
    .withCredentials("YOUR_CLIENT_ID", "YOUR_CLIENT_SECRET")
    .build();

client.transactions().create(
    "organization-123",
    CreateTransactionsObject.builder()
        .data(Arrays.asList(
            TransactionsDataUnion.transaction(
                TransactionsData.builder()
                    .id("12345610")
                    .attributes(
                        TransactionsAttributes.builder()
                            .userId("1234567890")
                            .amount(1000)
                            .subtotal(800)
                            .status("APPROVED")
                            .currency("USD")
                            .description("ADVANCEAUTO")
                            .authorizationDate("2021-07-02T17:47:06Z")
                            .paymentType("CARD")
                            .direction("DEBIT")
                            .merchant(
                                Merchant.builder()
                                    .id("12345678901234567")
                                    .name("ADVANCEAUTO")
                                    .addrStreet("125 Main St")
                                    .addrCity("Philadelphia")
                                    .addrState("PA")
                                    .addrZipcode("19147")
                                    .addrCountry("United States")
                                    .latitude("37.9419429")
                                    .longitude("-73.1446869")
                                    .storeId("12345")
                                    .build()
                            )
                            .cardBIN("123456")
                            .cardLastFour("4321")
                            .authorizationCode("123456")
                            .retrievalReferenceNumber("100804333919")
                            .systemTraceAuditNumber("333828")
                            .acquirerReferenceNumber("1234567890123456789012345678")
                            .transactionId("12345611")
                            .build()
                    )
                    .build()
            )
        ))
        .build()
);
```

All SDK methods return **typed responses and throw typed errors.**

## Handling Errors

If an API request fails (4xx or 5xx), the SDK throws a `KardApiApiException`.

```java
import com.kard.api.core.KardApiApiException;

try {
    client.users().create(...);
} catch (KardApiApiException e) {
    System.out.println("Status: " + e.statusCode());
    System.out.println("Body: " + e.body());
}
```

## Common Configuration Options

### Configure Retries

Retries are enabled by default (max 2 attempts) with exponential backoff. The SDK retries on status codes 408, 429, and 5xx.

```java
import com.kard.api.KardApiClient;

KardApiClient client = KardApiClient.builder()
    .maxRetries(1)
    .build();
```

### Set a Timeout

The SDK defaults to a 60 second timeout. Timeouts can be configured at the client or request level.

```java
import com.kard.api.KardApiClient;
import com.kard.api.core.RequestOptions;

// Client level
KardApiClient client = KardApiClient.builder()
    .timeout(30)
    .build();

// Request level
client.users().create(
    ...,
    RequestOptions.builder()
        .timeout(30)
        .build()
);
```

### Add Custom Headers

Headers can be configured at the client or request level.

```java
import com.kard.api.KardApiClient;
import com.kard.api.core.RequestOptions;

// Client level
KardApiClient client = KardApiClient.builder()
    .addHeader("X-Custom-Header", "custom-value")
    .build();

// Request level
client.users().create(
    ...,
    RequestOptions.builder()
        .addHeader("X-Request-Header", "request-value")
        .build()
);
```

## Access Raw HTTP Responses

To inspect headers or status codes, use `withRawResponse()`:

```java
CreateHttpResponse response = client.users().withRawResponse().create(...);

System.out.println(response.body());
System.out.println(response.headers().get("X-My-Header"));
```

## Custom HTTP Client

The SDK works with any `OkHttpClient` instance. By default, the SDK constructs one, but you can provide your own.

```java
import com.kard.api.KardApiClient;
import okhttp3.OkHttpClient;

OkHttpClient customClient = new OkHttpClient.Builder()
    .connectTimeout(30, java.util.concurrent.TimeUnit.SECONDS)
    .build();

KardApiClient client = KardApiClient.builder()
    .httpClient(customClient)
    .build();
```