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

# Authentication

> How Tender signs and authenticates API requests.

All requests require authentication. You can get your API credentials (Access ID and Access Secret) from the Tender dashboard.

Tender uses two authentication methods, depending on the endpoint:

| Method                | Headers required                                                               | Used by                                                    |
| --------------------- | ------------------------------------------------------------------------------ | ---------------------------------------------------------- |
| **Signed (HMAC)**     | `x-access-id`, `x-request-id`, `x-timestamp`, `authorization` (HMAC signature) | Agents, Conversions, Onramp, Payouts, Subwallets, Webhooks |
| **Basic (Access ID)** | `x-access-id` only                                                             | Payments, System (chains, currencies, rates)               |

Each endpoint page shows which method it uses in a note at the top.

***

## Basic (Access ID) Authentication

Payment and System endpoints (`/v1/api/payment/*` and `/v1/api/system/*`) only require your public access ID:

```http theme={null}
x-access-id: <YOUR_ACCESS_ID>
Content-Type: application/json
```

No request signing is needed for these endpoints. Your Access Secret is never sent.

***

## Signed (HMAC) Authentication

All other endpoints require HMAC signature-based authentication. Each request must include these headers:

```http theme={null}
x-access-id: <YOUR_ACCESS_ID>
x-request-id: <UUID_V4>
x-timestamp: <ISO_8601_TIMESTAMP>
authorization: <HMAC_SIGNATURE>
Content-Type: application/json
```

### Request Signing

To protect the integrity of your API requests, Tender uses HMAC-SHA256 signature authentication. This ensures that each request is securely verified and that the data hasn't been altered in transit.

Each request's headers must include:

1. **x-access-id**: Your public API access ID
2. **x-request-id**: A unique UUID v4 for each request
3. **x-timestamp**: Current timestamp in ISO 8601 format
4. **authorization**: Base64-encoded HMAC-SHA256 signature

#### How Signatures Are Generated

An **authorization** signature is generated using:

1. A JSON payload containing the timestamp, request ID, and access ID
2. Your API secret key
3. HMAC-SHA256 algorithm
4. Base64 encoding of the resulting hash

The signed payload structure:

```json theme={null}
{
  "timeStamp": "<ISO 8601 timestamp>",
  "requestId": "<UUID v4>",
  "accessId": "<your access ID>"
}
```

#### Signature Algorithm

```text theme={null}
hash = Base64(HMAC_SHA256(JSON.stringify(payload), accessSecret))
```

***

### Signed Request Example

<CodeGroup>
  ```javascript Node.js theme={null}
  import crypto from 'crypto';
  import { v4 as uuidv4 } from 'uuid';

  function generateSignature(accessId, accessSecret) {
    // Generate request ID and timestamp
    const requestId = uuidv4();
    const timeStamp = new Date().toISOString();
    
    // Create the payload to sign
    const payload = {
      timeStamp: timeStamp,
      requestId: requestId,
      accessId: accessId
    };
    
    // Generate HMAC-SHA256 signature
    const hmac = crypto.createHmac('sha256', accessSecret);
    hmac.update(JSON.stringify(payload));
    const signature = hmac.digest('base64');
    
    return {
      'x-access-id': accessId,
      'x-request-id': requestId,
      'x-timestamp': timeStamp,
      'authorization': signature,
      'Content-Type': 'application/json'
    };
  }

  // Usage
  const accessId = 'YOUR_ACCESS_ID';
  const accessSecret = 'YOUR_ACCESS_SECRET';

  const headers = generateSignature(accessId, accessSecret);
  console.log('Headers:', headers);

  // Make API request
  const response = await fetch('https://secureapi.tender.cash/v1/api/agent/create', {
    method: 'POST',
    headers: headers,
    body: JSON.stringify({
      firstName: 'John',
      lastName: 'Doe',
      email: 'john@example.com',
      phoneNumber: '1234567890',
      location: 'Lagos',
      address: '123 Main Street',
      country: 'Nigeria'
    })
  });

  const data = await response.json();
  console.log('Response:', data);
  ```

  ```python Python theme={null}
  import hmac
  import hashlib
  import base64
  import json
  import uuid
  from datetime import datetime
  import requests

  def generate_signature(access_id, access_secret):
      # Generate request ID and timestamp
      request_id = str(uuid.uuid4())
      timestamp = datetime.utcnow().isoformat() + 'Z'
      
      # Create the payload to sign
      payload = {
          "timeStamp": timestamp,
          "requestId": request_id,
          "accessId": access_id
      }
      
      # Generate HMAC-SHA256 signature
      message = json.dumps(payload)
      signature = base64.b64encode(
          hmac.new(
              access_secret.encode('utf-8'),
              message.encode('utf-8'),
              hashlib.sha256
          ).digest()
      ).decode('utf-8')
      
      return {
          'x-access-id': access_id,
          'x-request-id': request_id,
          'x-timestamp': timestamp,
          'authorization': signature,
          'Content-Type': 'application/json'
      }

  # Usage
  access_id = 'YOUR_ACCESS_ID'
  access_secret = 'YOUR_ACCESS_SECRET'

  headers = generate_signature(access_id, access_secret)
  print('Headers:', headers)

  # Make API request
  response = requests.post(
      'https://secureapi.tender.cash/v1/api/agent/create',
      headers=headers,
      json={
          'firstName': 'John',
          'lastName': 'Doe',
          'email': 'john@example.com',
          'phoneNumber': '1234567890',
          'location': 'Lagos',
          'address': '123 Main Street',
          'country': 'Nigeria'
      }
  )

  data = response.json()
  print('Response:', data)
  ```

  ```php PHP theme={null}
  <?php

  function generateSignature($accessId, $accessSecret) {
      // Generate request ID and timestamp
      $requestId = sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
          mt_rand(0, 0xffff), mt_rand(0, 0xffff),
          mt_rand(0, 0xffff),
          mt_rand(0, 0x0fff) | 0x4000,
          mt_rand(0, 0x3fff) | 0x8000,
          mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff)
      );
      $timeStamp = date('c');
      
      // Create the payload to sign
      $payload = [
          'timeStamp' => $timeStamp,
          'requestId' => $requestId,
          'accessId' => $accessId
      ];
      
      // Generate HMAC-SHA256 signature
      $message = json_encode($payload);
      $signature = base64_encode(hash_hmac('sha256', $message, $accessSecret, true));
      
      return [
          'x-access-id' => $accessId,
          'x-request-id' => $requestId,
          'x-timestamp' => $timeStamp,
          'authorization' => $signature,
          'Content-Type' => 'application/json'
      ];
  }

  // Usage
  $accessId = 'YOUR_ACCESS_ID';
  $accessSecret = 'YOUR_ACCESS_SECRET';

  $headers = generateSignature($accessId, $accessSecret);
  print_r($headers);

  // Make API request
  $ch = curl_init('https://secureapi.tender.cash/v1/api/agent/create');
  curl_setopt($ch, CURLOPT_POST, 1);
  curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
      'firstName' => 'John',
      'lastName' => 'Doe',
      'email' => 'john@example.com',
      'phoneNumber' => '1234567890',
      'location' => 'Lagos',
      'address' => '123 Main Street',
      'country' => 'Nigeria'
  ]));
  curl_setopt($ch, CURLOPT_HTTPHEADER, [
      'x-access-id: ' . $headers['x-access-id'],
      'x-request-id: ' . $headers['x-request-id'],
      'x-timestamp: ' . $headers['x-timestamp'],
      'authorization: ' . $headers['authorization'],
      'Content-Type: application/json'
  ]);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

  $response = curl_exec($ch);
  curl_close($ch);

  echo 'Response: ' . $response;
  ?>
  ```
</CodeGroup>

***

## Important Notes

* **Keep your Access Secret secure**: Never expose it in client-side code or public repositories
* **Generate a new request ID** for each request using UUID v4
* **Use ISO 8601 format** for timestamps (e.g., `2025-03-15T09:45:53.000Z`)
* **Invalid signatures** will result in a 401 Unauthorized error

For troubleshooting authentication errors, see the [Errors](/api-reference/errors) section.
