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

# API Security

> This page provides important information about the details you need to know before making API requests.

# Secure API and Idempotency Mechanism

## Idempotency-Key Header

### What is it?

The `Idempotency-Key` is a unique, cryptographically generated value added to each API request header.\
It ensures that **retries of the same request are not executed more than once** by the server.\
This is especially important for operations that create or modify resources (e.g., payments, transactions, device records), where duplicate processing could lead to inconsistent data or unintended side effects.

### Why is it used?

* **Prevents duplicates:** If a client retries a request due to a timeout or network error, the server can detect the same `Idempotency-Key` and ignore duplicate executions.
* **Ensures consistency:** Clients can safely retry requests without worrying about unintended multiple writes.
* **Improves reliability:** Makes APIs more resilient against network instability.

***

### Example Postman Pre-request script for API clients

```javascript theme={null}
// Use the body of the request as the payload.
const {Url} = require('postman-collection');
let payloadString = pm.request.body.raw;

if ( ! payloadString ) {
    let url = new Url(pm.environment.get("url") + pm.request.url.getPath());
    payloadString = "/api" + url.getPath();
    console.log( 'Payload: ' + payloadString );
} else {
    console.log( 'Payload: ' + JSON.stringify ( payloadString ) );
}

// Load the CryptoJS library required for the SHA256 hash operation.
eval(pm.globals.get("CryptoJS"));

// Calculate the SHA256 hash of the payload.
const hash = CryptoJS.SHA256(payloadString);

// Obtain the hexadecimal equivalent of the hash value.
const hashHex = hash.toString(CryptoJS.enc.Hex).toUpperCase();
console.log ( 'SHA256 Hash: ' + hashHex );

// Calculate the epoch millisecond of the current time.
const currentTime = new Date().getTime();
const currentTimeString = currentTime.toString();
console.log ( 'Epoch ms: ' + currentTimeString );

// Pad the length of currentTimeString to a multiple of 8.
const paddedCurrentTimeString = currentTimeString.padStart(Math.ceil(currentTimeString.length / 8) * 8, '0');
console.log( 'paddedCurrentTimeString: ' + paddedCurrentTimeString );

// Generate a 3DES encryption key and iv (initialization vector).
const key = CryptoJS.enc.Hex.parse( hashHex ); // Extract the 3DES key here.
const message = CryptoJS.enc.Utf8.parse(paddedCurrentTimeString);

const encrypted = CryptoJS.TripleDES.encrypt( paddedCurrentTimeString, key, {
    mode: CryptoJS.mode.ECB,
    padding: CryptoJS.pad.NoPadding
});

// Convert the result of the encryption to a Hex String.
const hexString = encrypted.ciphertext.toString().toUpperCase();
console.log ( 'Idempotency-Key: ' + hexString );

// Assign the result of the cryptographic operation to the “Idempotency-Key” header of the request.
pm.request.headers.add({ key: 'Idempotency-Key', value: hexString });
```

### How is it calculated in the Pre-request Script?

The provided Postman pre-request script generates the `Idempotency-Key` as follows:

1. **Payload extraction**
   * Uses the raw request body as the payload.
   * If the body is empty, falls back to the request URL path.

2. **SHA256 hashing**
   * Computes a SHA256 hash of the payload string.
   * Converts the result into an uppercase hex string.
   * This ensures a deterministic and unique base for the key.

3. **Timestamp inclusion**
   * Takes the current epoch time in milliseconds.
   * Pads the string to make its length a multiple of 8.
   * This adds **uniqueness per request**, even if the payload is identical.

4. **TripleDES encryption**
   * Uses the SHA256 hash as the key for 3DES encryption.
   * Encrypts the padded timestamp in ECB mode without padding.
   * Produces an encrypted value as a hex string.

5. **Final header assignment**
   * The resulting encrypted hex string becomes the `Idempotency-Key`.
   * Added to the request headers automatically:
     ```js theme={null}
     pm.request.headers.add({ key: 'Idempotency-Key', value: hexString });
     ```

***

### Example Output (from console logs)

```
Payload: "{'screenName':'bienport.demo', 'password':'demo', 'rememberMe':true}"
SHA256 Hash: 65179C12FE83D08F....
Epoch ms: 1756141928597
paddedCurrentTimeString: 0001756141928597
Idempotency-Key: 1F11611E2483A1C360CE711B791A0711
POST https://apigw.bienport.com/api/auth/login
```

***

### Summary

* **Purpose:** Guarantees safe retries by preventing duplicate request execution.
* **Mechanism:** Combines request payload + timestamp + encryption to create a unique key.
* **Usage:** Always included in the request header automatically when running an API client.
