> For the complete documentation index, see [llms.txt](https://docs.ledig.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.ledig.io/auth/authentication.md).

# Authentication

All requests to the **Ledig API** (except for the open `/health` endpoint) require authentication using **API keys with HMAC signing**. This ensures every request is verifiable and secure.

***

## 🔑 API Keys

* You can generate API keys in the **Settings** section of your Ledig dashboard.
* Each key pair consists of:
  * **API Key** → Public identifier (`x-ledig-key`)
  * **Secret Key** → Used to generate HMAC signatures (⚠️ never share or hardcode into frontend code)

👉 Generating a new key **revokes the previous one** and issues a new secret. Always update your integration accordingly.

***

## 📌 Required Headers

Every authenticated request must include the following headers:

| Header              | Description                                                               |
| ------------------- | ------------------------------------------------------------------------- |
| `x-ledig-key`       | Your API key (public identifier)                                          |
| `x-ledig-timestamp` | Current UNIX timestamp (in seconds)                                       |
| `x-ledig-signature` | HMAC-SHA256 signature generated using your secret key and request payload |

***

## 🧮 Signature Calculation

The signature is built as follows:

```
payload = "{timestamp}.{HTTP_METHOD}.{PATH_WITH_QUERY}.{BODY}"
signature = HMAC_SHA256(secret, payload)
x-ledig-signature = "v1=" + base64(signature)
```

* **timestamp** → The value sent in `x-ledig-timestamp`
* **HTTP\_METHOD** → `GET`, `POST`, etc.
* **PATH\_WITH\_QUERY** → The path including any query string (e.g. `/v1/rates?pair=USDT-NGN`)
* **BODY** → For `POST`/`PUT` requests, the raw request body. For `GET`, use an empty string.

***

## 📝 Sample Payload Debug

When debugging your integration, it helps to log the **signed payload string**.\
This is the exact string your system will HMAC-sign.

**Example GET request:**

```
1700000000.GET./v1/rates.
```

**Example POST request:**

```
1700000000.POST./v1/instant_conversion.{"contract_id":"17559","from_amount":1000}
```

If your signature doesn’t match, first confirm your **payload string** looks exactly like this.

***

## 📝 Example (cURL)

```bash
curl -X GET "https://api.ledig.io/v1/rates"   -H "x-ledig-key: YOUR_API_KEY"   -H "x-ledig-timestamp: 1700000000"   -H "x-ledig-signature: v1=AbCdEfGhIjKlMn..."   -H "Content-Type: application/json"
```

***

## 💻 Example Code

### Node.js

```javascript
const crypto = require("crypto");

function signRequest(secret, timestamp, method, path, body = "") {
  const payload = `${timestamp}.${method}.${path}.${body}`;
  const hmac = crypto.createHmac("sha256", secret).update(payload).digest("base64");
  return "v1=" + hmac;
}
```

### Python

```python
import hmac, hashlib, base64

def sign_request(secret, timestamp, method, path, body=""):
    payload = f"{timestamp}.{method}.{path}.{body}"
    sig = hmac.new(secret.encode(), payload.encode(), hashlib.sha256).digest()
    return "v1=" + base64.b64encode(sig).decode()
```

***

## ⚠️ Best Practices

* Always **use the server side** to sign requests (never expose your secret).
* Ensure your system clock is accurate (we allow a few seconds of drift).
* Rotate keys periodically and delete unused ones.
