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

# Authentication & Idempotency

> Authenticate with API keys and prevent duplicate requests with Idempotency-Key

## Authentication

Use your API key as a Bearer token in the <code>Authorization</code> header for every request.

```http theme={"dark"}
Authorization: Bearer <YOUR_SECRET_KEY>
```

* All requests must use HTTPS (TLS 1.2+). Requests made over HTTP are rejected.
* Keep your secret keys secure and do not embed them in client-side code or mobile apps.
* We return a per-request <code>X-Request-Id</code> you can reference when contacting support.

<Warning>
  Never expose your secret API key in client-side code or mobile apps.
</Warning>

### Idempotency (required for live POST requests)

To safely retry POST requests without duplicating operations, send an idempotency key:

```http theme={"dark"}
Idempotency-Key: <a-unique-uuid-per-merchantTransactionId>
```

* Tie the idempotency key to your <code>merchantTransactionId</code>.
* Reuse the exact same idempotency key when retrying the same logical request.
* Repeating a POST with the same key returns the original response as long as method, path, and body are identical.
* Conflicting retries (same key but different body) return <code>409 conflict</code>.

<CodeGroup>
  ```javascript Node.js theme={"dark"}
  import crypto from 'node:crypto'

  async function charge(body, idempotencyKey) {
    const res = await fetch('https://api.fingopay.io/v1/mpesa/charge', {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${process.env.FINGO_API_KEY}`,
        'Content-Type': 'application/json',
        'Idempotency-Key': idempotencyKey
      },
      body: JSON.stringify(body)
    });
    return res.json();
  }

  const idempotencyKey = crypto.randomUUID();
  await charge({ phoneNumber: '+254712345678', amount: 150000, merchantTransactionId: 'order_12345' }, idempotencyKey);
  // If you retry the same request, reuse the same key:
  await charge({ phoneNumber: '+254712345678', amount: 150000, merchantTransactionId: 'order_12345' }, idempotencyKey);
  ```

  ```python Python theme={"dark"}
  import os, uuid, requests

  def charge(body: dict, idempotency_key: str):
      headers = {
          'Authorization': f"Bearer {os.environ['FINGO_API_KEY']}",
          'Content-Type': 'application/json',
          'Idempotency-Key': idempotency_key,
      }
      r = requests.post('https://api.fingopay.io/v1/mpesa/charge', json=body, headers=headers)
      return r.json()

  key = str(uuid.uuid4())
  payload = {
      'phoneNumber': '+254712345678',
      'amount': 150000,
      'merchantTransactionId': 'order_12345',
  }
  charge(payload, key)
  # Retry the same logical request with the same key:
  charge(payload, key)
  ```
</CodeGroup>
