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

# Authentication

> Secure API access with JWT tokens

## Overview

The Hedge Pay API uses **JWT (JSON Web Tokens)** for authentication. All API requests must include a valid access token in the Authorization header.

<Note>
  Access tokens expire after 7 days. We recommend implementing automatic token refresh to avoid service interruptions.
</Note>

## Authentication Flow

```mermaid theme={null}
sequenceDiagram
    participant App as Your Application
    participant API as Hedge Pay API
    participant User as End User
    
    App->>API: POST /auth/token (API Key + Partner ID)
    API-->>App: Access Token (JWT)
    App->>API: API Request + Bearer Token
    API-->>App: Response
    
    Note over App,API: Token expires after 7 days
    
    App->>API: POST /auth/refresh
    API-->>App: New Access Token
```

## Getting Your Credentials

1. Sign up at [dashboard.hedgepay.com](https://dashboard.hedgepay.com)
2. Navigate to **Settings → API Keys**
3. Generate your API credentials:
   * **API Key**: Public identifier for your application
   * **API Secret**: Secret key (keep this secure!)
   * **Partner ID**: Your unique partner identifier

<Warning>
  Never expose your API Secret in client-side code or public repositories. Store it securely in environment variables.
</Warning>

## Generate Access Token

Exchange your API credentials for an access token:

<CodeGroup>
  ```javascript JavaScript theme={null}
  const response = await fetch('https://api.hedgepay.com/v1/auth/token', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      api_key: 'pk_live_abc123...',
      api_secret: 'sk_live_xyz789...',
      partner_id: 'partner_123'
    })
  });

  const { access_token, expires_in } = await response.json();

  // Store the token securely
  localStorage.setItem('hedge_token', access_token);
  ```

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

  response = requests.post(
      'https://api.hedgepay.com/v1/auth/token',
      json={
          'api_key': 'pk_live_abc123...',
          'api_secret': 'sk_live_xyz789...',
          'partner_id': 'partner_123'
      }
  )

  data = response.json()
  access_token = data['access_token']
  expires_in = data['expires_in']

  # Store the token securely
  ```

  ```bash cURL theme={null}
  curl -X POST https://api.hedgepay.com/v1/auth/token \
    -H "Content-Type: application/json" \
    -d '{
      "api_key": "pk_live_abc123...",
      "api_secret": "sk_live_xyz789...",
      "partner_id": "partner_123"
    }'
  ```
</CodeGroup>

### Response

```json theme={null}
{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "Bearer",
  "expires_in": 604800,
  "partner_id": "partner_123",
  "scopes": [
    "users:read",
    "users:write",
    "accounts:read",
    "accounts:write",
    "transfers:read",
    "transfers:write"
  ]
}
```

## Using the Access Token

Include the access token in the Authorization header for all API requests:

<CodeGroup>
  ```javascript JavaScript theme={null}
  const response = await fetch('https://api.hedgepay.com/v1/users', {
    method: 'GET',
    headers: {
      'Authorization': `Bearer ${access_token}`,
      'Content-Type': 'application/json'
    }
  });
  ```

  ```python Python theme={null}
  response = requests.get(
      'https://api.hedgepay.com/v1/users',
      headers={
          'Authorization': f'Bearer {access_token}',
          'Content-Type': 'application/json'
      }
  )
  ```

  ```bash cURL theme={null}
  curl https://api.hedgepay.com/v1/users \
    -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
  ```
</CodeGroup>

## Token Refresh

Refresh your token before it expires to maintain uninterrupted service:

<CodeGroup>
  ```javascript JavaScript theme={null}
  // Refresh token before expiry
  const refreshToken = async () => {
    const response = await fetch('https://api.hedgepay.com/v1/auth/refresh', {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${current_token}`,
        'Content-Type': 'application/json'
      }
    });
    
    const { access_token } = await response.json();
    return access_token;
  };

  // Auto-refresh implementation
  setInterval(async () => {
    const newToken = await refreshToken();
    localStorage.setItem('hedge_token', newToken);
  }, 6 * 24 * 60 * 60 * 1000); // Refresh every 6 days
  ```

  ```python Python theme={null}
  import time
  import threading

  def refresh_token():
      response = requests.post(
          'https://api.hedgepay.com/v1/auth/refresh',
          headers={
              'Authorization': f'Bearer {current_token}',
              'Content-Type': 'application/json'
          }
      )
      
      data = response.json()
      return data['access_token']

  # Auto-refresh implementation
  def auto_refresh():
      while True:
          time.sleep(6 * 24 * 60 * 60)  # Wait 6 days
          global access_token
          access_token = refresh_token()

  refresh_thread = threading.Thread(target=auto_refresh, daemon=True)
  refresh_thread.start()
  ```
</CodeGroup>

## Token Revocation

Revoke a token when it's no longer needed:

<CodeGroup>
  ```javascript JavaScript theme={null}
  await fetch('https://api.hedgepay.com/v1/auth/revoke', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${access_token}`,
      'Content-Type': 'application/json'
    }
  });
  ```

  ```python Python theme={null}
  requests.post(
      'https://api.hedgepay.com/v1/auth/revoke',
      headers={
          'Authorization': f'Bearer {access_token}',
          'Content-Type': 'application/json'
      }
  )
  ```
</CodeGroup>

## Scopes and Permissions

Tokens are issued with specific scopes that determine API access:

| Scope             | Description                     |
| ----------------- | ------------------------------- |
| `users:read`      | Read user information           |
| `users:write`     | Create and update users         |
| `accounts:read`   | View connected bank accounts    |
| `accounts:write`  | Connect and disconnect accounts |
| `transfers:read`  | View transfer history           |
| `transfers:write` | Initiate and cancel transfers   |
| `roundups:read`   | View round-up settings          |
| `roundups:write`  | Modify round-up settings        |
| `webhooks:write`  | Manage webhook subscriptions    |

## Environment-Specific Endpoints

<Tabs>
  <Tab title="Production">
    ```
    Base URL: https://api.hedgepay.com
    Auth URL: https://api.hedgepay.com/v1/auth/token
    ```
  </Tab>

  <Tab title="Sandbox">
    ```
    Base URL: https://api-sandbox.hedgepay.com
    Auth URL: https://api-sandbox.hedgepay.com/v1/auth/token
    ```

    <Info>
      Use sandbox credentials for testing. Sandbox tokens have the same format but only work in the sandbox environment.
    </Info>
  </Tab>
</Tabs>

## Error Handling

Authentication errors return standard HTTP status codes:

| Status Code | Error                 | Description                      |
| ----------- | --------------------- | -------------------------------- |
| `401`       | `INVALID_CREDENTIALS` | Invalid API key or secret        |
| `401`       | `TOKEN_EXPIRED`       | Access token has expired         |
| `401`       | `TOKEN_INVALID`       | Malformed or invalid token       |
| `403`       | `INSUFFICIENT_SCOPE`  | Token lacks required permissions |
| `429`       | `RATE_LIMITED`        | Too many authentication attempts |

### Error Response Example

```json theme={null}
{
  "error": {
    "code": "TOKEN_EXPIRED",
    "message": "The access token has expired. Please refresh or generate a new token.",
    "details": {
      "expired_at": "2024-01-15T10:30:00Z"
    }
  },
  "request_id": "req_abc123xyz"
}
```

## Security Best Practices

<AccordionGroup>
  <Accordion title="Store Credentials Securely" icon="lock">
    * Never commit API secrets to version control
    * Use environment variables or secret management services
    * Rotate API keys regularly
    * Use different keys for development and production
  </Accordion>

  <Accordion title="Implement Token Refresh" icon="arrows-rotate">
    * Refresh tokens before expiry
    * Handle refresh failures gracefully
    * Implement exponential backoff for retries
    * Store refresh timestamps
  </Accordion>

  <Accordion title="Secure Client Applications" icon="shield">
    * Never expose API secrets in client-side code
    * Use server-side proxy for API calls
    * Implement CORS properly
    * Validate webhook signatures
  </Accordion>

  <Accordion title="Monitor and Audit" icon="chart-line">
    * Log all authentication events
    * Monitor for unusual patterns
    * Set up alerts for failed authentications
    * Review API key usage regularly
  </Accordion>
</AccordionGroup>

## SDK Authentication

Our SDKs handle authentication automatically:

<CodeGroup>
  ```javascript JavaScript SDK theme={null}
  import { HedgeSDK } from '@hedge/sdk-core';

  const hedge = new HedgeSDK({
    apiKey: process.env.HEDGE_API_KEY,
    apiSecret: process.env.HEDGE_API_SECRET,
    partnerId: process.env.HEDGE_PARTNER_ID
  });

  // SDK handles token generation and refresh automatically
  await hedge.authenticate();
  ```

  ```python Python SDK theme={null}
  from hedge_roundups import HedgeClient

  hedge = HedgeClient(
      api_key=os.environ['HEDGE_API_KEY'],
      api_secret=os.environ['HEDGE_API_SECRET'],
      partner_id=os.environ['HEDGE_PARTNER_ID']
  )

  # Authentication is handled automatically
  ```
</CodeGroup>

## Next Steps

<CardGroup cols={2}>
  <Card title="API Reference" icon="code" href="/api-reference/introduction">
    Start making API calls
  </Card>

  <Card title="Webhooks" icon="webhook" href="/guides/handling-webhooks">
    Set up webhook authentication
  </Card>
</CardGroup>
