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

# Authentication

> Secure API authentication for StateSet Commerce Network

<Info>
  **Quick Start**: Get your API keys from the [StateSet Dashboard](https://dashboard.stateset.com) and make your first authenticated request in minutes.
</Info>

## 🔐 Overview

StateSet uses API keys to authenticate requests. Authentication is performed via HTTP headers using the Bearer token format. All API requests must be made over HTTPS.

## 🔑 API Key Types

<CardGroup cols={2}>
  <Card title="Test Mode" icon="flask">
    **Prefix**: `sk_test_`

    Use for development and testing. Transactions are simulated and no real money moves.
  </Card>

  <Card title="Live Mode" icon="circle-check">
    **Prefix**: `sk_live_`

    Use for production. All transactions are real and irreversible.
  </Card>
</CardGroup>

<Warning>
  Never expose your secret API keys in client-side code, public repositories, or anywhere else accessible to the public.
</Warning>

## 📋 Authentication Methods

### Standard Authentication

Include your API key in the `Authorization` header:

<CodeGroup>
  ```bash cURL theme={null}
  curl https://api.stateset.com/v1/account/balance \
    -H "Authorization: Bearer sk_test_your_actual_key_here"
  ```

  ```javascript Node.js theme={null}
  const axios = require('axios');

  const response = await axios.get('https://api.stateset.com/v1/account/balance', {
    headers: {
      'Authorization': 'Bearer sk_test_your_actual_key_here'
    }
  });
  ```

  ```python Python theme={null}
  import requests

  response = requests.get(
      'https://api.stateset.com/v1/account/balance',
      headers={
          'Authorization': 'Bearer sk_test_your_actual_key_here'
      }
  )
  ```

  ```go Go theme={null}
  client := &http.Client{}
  req, _ := http.NewRequest("GET", "https://api.stateset.com/v1/account/balance", nil)
  req.Header.Add("Authorization", "Bearer sk_test_your_actual_key_here")
  resp, _ := client.Do(req)
  ```
</CodeGroup>

### SDK Authentication

When using our official SDKs, initialize with your API key:

<CodeGroup>
  ```javascript Node.js theme={null}
  import { StateSet } from '@stateset/sdk';

  const stateset = new StateSet({
    apiKey: process.env.STATESET_API_KEY // Best practice: use environment variables
  });
  ```

  ```python Python theme={null}
  from stateset import StateSet
  import os

  stateset = StateSet(
      api_key=os.getenv('STATESET_API_KEY')  # Best practice: use environment variables
  )
  ```

  ```go Go theme={null}
  import (
      "github.com/stateset/stateset-go"
      "os"
  )

  client := stateset.NewClient(
      os.Getenv("STATESET_API_KEY"),  // Best practice: use environment variables
  )
  ```

  ```ruby Ruby theme={null}
  require 'stateset'

  Stateset.api_key = ENV['STATESET_API_KEY']  # Best practice: use environment variables
  ```
</CodeGroup>

## 🛡️ Security Best Practices

<AccordionGroup>
  <Accordion title="1. Use Environment Variables" icon="key">
    Never hardcode API keys in your source code. Use environment variables:

    ```bash .env theme={null}
        STATESET_API_KEY=sk_test_your_actual_key_here
    ```

    ```javascript theme={null}
    // Load from environment
    const apiKey = process.env.STATESET_API_KEY;
    ```
  </Accordion>

  <Accordion title="2. Implement Key Rotation" icon="rotate">
    Regularly rotate your API keys (recommended every 90 days):

    1. Generate a new API key in the dashboard
    2. Update your application to use the new key
    3. Verify everything works correctly
    4. Revoke the old key
  </Accordion>

  <Accordion title="3. Use Separate Keys per Environment" icon="code-branch">
    * **Development**: Use test keys with limited permissions
    * **Staging**: Use test keys with production-like permissions
    * **Production**: Use live keys with minimal required permissions
  </Accordion>

  <Accordion title="4. Restrict Key Permissions" icon="shield-halved">
    Create keys with only the permissions needed:

    ```javascript theme={null}
    // Dashboard API
    const key = await stateset.apiKeys.create({
      name: 'Read-only Analytics Key',
      permissions: ['analytics:read', 'transactions:read']
    });
    ```
  </Accordion>

  <Accordion title="5. Monitor Key Usage" icon="chart-line">
    Track API key usage to detect anomalies:

    ```javascript theme={null}
    const usage = await stateset.apiKeys.usage({
      keyId: 'key_abc123',
      startDate: '2024-01-01',
      endDate: '2024-01-31'
    });
    ```
  </Accordion>
</AccordionGroup>

## 🔒 Advanced Authentication

### HMAC Signatures (High-Security Operations)

For sensitive operations like large transfers or issuance, add HMAC signatures:

```javascript theme={null}
const crypto = require('crypto');

function createHmacSignature(payload, secret) {
  const timestamp = Math.floor(Date.now() / 1000);
  const message = `${timestamp}.${JSON.stringify(payload)}`;
  
  const signature = crypto
    .createHmac('sha256', secret)
    .update(message)
    .digest('hex');
    
  return {
    signature,
    timestamp
  };
}

// Use in request
const payload = { amount: '10000.00', to: 'stateset1abc...' };
const { signature, timestamp } = createHmacSignature(payload, process.env.HMAC_SECRET);

const response = await axios.post('https://api.stateset.com/v1/stablecoin/transfer', payload, {
  headers: {
    'Authorization': `Bearer ${apiKey}`,
    'X-Signature': signature,
    'X-Timestamp': timestamp
  }
});
```

### OAuth 2.0 (Partner Integrations)

For third-party integrations, use OAuth 2.0:

```javascript theme={null}
// 1. Redirect user to authorize
const authUrl = `https://auth.stateset.com/oauth/authorize?
  client_id=${CLIENT_ID}&
  redirect_uri=${REDIRECT_URI}&
  response_type=code&
  scope=payments:read+payments:write`;

// 2. Exchange code for token
const tokenResponse = await axios.post('https://auth.stateset.com/oauth/token', {
  grant_type: 'authorization_code',
  code: authorizationCode,
  client_id: CLIENT_ID,
  client_secret: CLIENT_SECRET,
  redirect_uri: REDIRECT_URI
});

// 3. Use access token
const response = await axios.get('https://api.stateset.com/v1/payments', {
  headers: {
    'Authorization': `Bearer ${tokenResponse.data.access_token}`
  }
});
```

## 📊 Rate Limits

API keys have different rate limits based on your plan:

<table>
  <thead>
    <tr>
      <th>Plan</th>
      <th>Requests/Second</th>
      <th>Requests/Day</th>
      <th>Burst Limit</th>
    </tr>
  </thead>

  <tbody>
    <tr>
      <td>Free</td>
      <td>10</td>
      <td>1,000</td>
      <td>20</td>
    </tr>

    <tr>
      <td>Starter</td>
      <td>100</td>
      <td>100,000</td>
      <td>200</td>
    </tr>

    <tr>
      <td>Growth</td>
      <td>1,000</td>
      <td>10,000,000</td>
      <td>2,000</td>
    </tr>

    <tr>
      <td>Enterprise</td>
      <td>Custom</td>
      <td>Custom</td>
      <td>Custom</td>
    </tr>
  </tbody>
</table>

### Handling Rate Limits

```javascript theme={null}
async function makeRequestWithRetry(url, options, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    try {
      const response = await axios.get(url, options);
      return response.data;
    } catch (error) {
      if (error.response?.status === 429) {
        const retryAfter = error.response.headers['retry-after'] || 2 ** i;
        console.log(`Rate limited. Retrying after ${retryAfter} seconds...`);
        await new Promise(resolve => setTimeout(resolve, retryAfter * 1000));
      } else {
        throw error;
      }
    }
  }
  throw new Error('Max retries exceeded');
}
```

## 🚨 Error Responses

Authentication errors return standardized responses:

```json theme={null}
{
  "error": {
    "type": "authentication_error",
    "message": "Invalid API key provided",
    "code": "invalid_api_key",
    "status": 401
  }
}
```

Common authentication errors:

| Error Code                 | Description                    | Solution                          |
| -------------------------- | ------------------------------ | --------------------------------- |
| `missing_api_key`          | No API key provided            | Include `Authorization` header    |
| `invalid_api_key`          | API key is invalid             | Check key format and validity     |
| `expired_api_key`          | API key has expired            | Generate a new key                |
| `insufficient_permissions` | Key lacks required permissions | Use a key with proper permissions |
| `rate_limit_exceeded`      | Too many requests              | Implement backoff and retry       |

## 🔄 Key Management API

Programmatically manage your API keys:

```javascript theme={null}
// List all keys
const keys = await stateset.apiKeys.list();

// Create a new key
const newKey = await stateset.apiKeys.create({
  name: 'Mobile App Key',
  permissions: ['payments:create', 'payments:read'],
  expires_at: '2024-12-31T23:59:59Z'
});

// Revoke a key
await stateset.apiKeys.revoke('key_abc123');

// Update key permissions
await stateset.apiKeys.update('key_abc123', {
  permissions: ['payments:read']
});
```

## 🧪 Testing Authentication

Use our test endpoint to verify your authentication:

```bash theme={null}
curl https://api.stateset.com/v1/auth/test \
  -H "Authorization: Bearer sk_test_your_actual_key_here"
```

Success response:

```json theme={null}
{
  "authenticated": true,
  "key_id": "key_abc123",
  "permissions": ["payments:create", "payments:read"],
  "mode": "test"
}
```

## 📱 Mobile & Frontend Security

<Warning>
  Never use secret API keys in mobile apps or frontend code. Use our public keys or implement a backend proxy.
</Warning>

### Public Keys (Read-Only Operations)

```javascript theme={null}
// Safe to use in frontend
const publicKey = 'pk_test_TYooMQauvdEDq54NiTphI7jx';

// Limited to read-only operations
const balance = await fetch(`https://api.stateset.com/v1/public/balance/${address}`, {
  headers: {
    'Authorization': `Bearer ${publicKey}`
  }
});
```

### Backend Proxy Pattern

```javascript theme={null}
// Frontend
const response = await fetch('/api/stateset-proxy/payment', {
  method: 'POST',
  body: JSON.stringify({ amount: 100, recipient: 'stateset1abc...' })
});

// Backend (Node.js/Express)
app.post('/api/stateset-proxy/payment', authenticate, async (req, res) => {
  const payment = await stateset.payments.create({
    ...req.body,
    customer: req.user.id
  });
  res.json(payment);
});
```

## 🆘 Troubleshooting

<AccordionGroup>
  <Accordion title="401 Unauthorized">
    * Verify API key is correct and properly formatted
    * Check if key is expired or revoked
    * Ensure `Bearer` prefix is included
    * Confirm using correct environment (test vs live)
  </Accordion>

  <Accordion title="403 Forbidden">
    * Check if key has required permissions
    * Verify you're not exceeding rate limits
    * Ensure accessing allowed endpoints for key type
  </Accordion>

  <Accordion title="Key Not Working">
    Run diagnostics:

    ```bash theme={null}
    curl -v https://api.stateset.com/v1/auth/test \
      -H "Authorization: Bearer YOUR_API_KEY"
    ```

    Check response headers and body for details.
  </Accordion>
</AccordionGroup>

## 📚 Next Steps

<CardGroup cols={2}>
  <Card title="Quick Start Guide" icon="rocket" href="/quick-start">
    Make your first API call in 5 minutes
  </Card>

  <Card title="SDKs & Libraries" icon="code" href="/sdks">
    Official SDKs for all major languages
  </Card>

  <Card title="Webhooks" icon="webhook" href="/webhooks">
    Secure webhook authentication
  </Card>

  <Card title="API Reference" icon="book" href="/api-reference">
    Complete API documentation
  </Card>
</CardGroup>
