> 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/js/authentication.md).

# Authentication

How the Crypto Chief Node.js SDK authenticates and signs every request.

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

```ts
import { CryptoChiefClient } from '@cryptochiefs/cryptochief-crypto-processing-node';

const client = new CryptoChiefClient({
  merchantId: process.env.MERCHANT_ID!,
  apiKey: process.env.API_KEY!,
});
```

The client is stateless beyond its configuration — create one and reuse it across your whole app.

## Configuration options

```ts
import { readFileSync } from 'node:fs';

const client = new CryptoChiefClient({
  merchantId: process.env.MERCHANT_ID!,
  apiKey: process.env.API_KEY!,
  baseUrl: 'https://api-processing.crypto-chief.com', // default
  timeoutMs: 60_000,                                  // per-attempt request timeout
  retries: 3,                                         // retry 5xx + transport errors
  retryBackoff: { baseMs: 200, maxMs: 5_000 },        // exponential + jitter
  userAgent: 'my-service/1.0',
  rsaPrivateKey: readFileSync('./rsa_private.pem', 'utf8'), // optional — wallet decryption
  // fetch: customFetch,                              // optional — inject a custom fetch
  // logger: { debug: (m, meta) => console.debug(m, meta) },
});
```

Every method also accepts a per-call `{ signal }` — pass an `AbortSignal` to cancel a request and its retries:

```ts
const ac = new AbortController();
setTimeout(() => ac.abort(), 3_000);
await client.payouts.info(uuid, { signal: ac.signal });
```

{% 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 canonicalizes the JSON body (recursively sorted keys, HTML-escaped `< > &`), base64-encodes it, appends your API key, and MD5-hashes the result to produce the `Signature`. The same scheme verifies [webhooks](/processing/js/guides/webhooks.md), so one secret secures both directions.
