> For the complete documentation index, see [llms.txt](https://docs-sdk.crypto-chief.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs-sdk.crypto-chief.com/processing/java/authentication.md).

# Authentication

Every request to the Crypto Processing API is authenticated with two HTTP headers. **The SDK builds and sets them for you** — you only provide your Merchant ID and API key.

```
Merchant:  <your Merchant ID>
Signature: hex(md5(base64(canonicalJSON(body)) + API_KEY))
```

## Credentials

Both values come from your dashboard → **Integration** tab:

* **Merchant ID** — identifies your project.
* **API key** — the **signing secret**. It never leaves your server; the SDK uses it to compute the `Signature` and to verify incoming webhooks.

{% hint style="warning" %}
Treat the API key like a password. Load it from an environment variable and keep it server-side — never commit it or ship it in client apps.
{% endhint %}

## Initialize the client

```java
import com.cryptochief.processing.CryptoChiefClient;

var client = CryptoChiefClient.create(
    System.getenv("CRYPTO_CHIEF_MERCHANT_ID"),
    System.getenv("CRYPTO_CHIEF_API_KEY"));
```

`CryptoChiefClient` is safe to share across threads and implements `AutoCloseable` — wrap calls with try-with-resources to release the OkHttp pool on shutdown:

```java
try (var client = CryptoChiefClient.create(merchantId, apiKey)) {
    // use client
}
```

## Configuration options

```java
import com.cryptochief.processing.CryptoChiefClient;
import com.cryptochief.processing.Options;
import com.cryptochief.processing.rsa.RsaKeyLoader;
import java.time.Duration;

var client = new CryptoChiefClient(Options.builder()
    .merchantId("MERCHANT_ID")
    .apiKey("API_KEY")
    .baseUrl("https://api-processing.crypto-chief.com")    // default
    .requestTimeout(Duration.ofSeconds(60))
    .maxRetries(3)                                          // retry 5xx + transport errors
    .initialRetryDelay(Duration.ofMillis(200))
    .maxRetryDelay(Duration.ofSeconds(5))
    .userAgent("my-service/1.0")
    .rsaPrivateKey(RsaKeyLoader.loadPrivateKeyFromFile("./rsa_private.pem")) // optional
    .httpClient(mySharedOkHttp)                             // optional — share connection pool
    .build());
```

When you supply your own `httpClient`, the SDK never closes it — that's your responsibility.

{% hint style="info" %}
**Test mode** is a per-project toggle in the dashboard, not a separate base URL. Point a test-mode project's credentials at the same client.
{% endhint %}

## How signing works

The client serialises the body to canonical JSON (recursively sorted keys, compact, UTF-8) via Jackson, base64-encodes the bytes, appends your API key, and MD5-hashes the result to produce the `Signature`. The same scheme verifies [webhooks](/processing/java/guides/webhooks.md), so one secret secures both directions.
