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

# Authentication

> Learn how to authenticate your API requests with EcoEvents

## Overview

The EcoEvents API uses API keys and JWT tokens for authentication. All API requests must be authenticated to protect your data and ensure secure access to our platform.

<Warning>
  Never share your API keys or commit them to version control. Treat them like passwords and store them securely using environment variables or a secrets manager.
</Warning>

## Authentication Methods

EcoEvents supports two authentication methods:

### 1. API Keys (Recommended for Server-to-Server)

API keys are ideal for server-side applications and long-running services. They don't expire unless manually revoked.

### 2. JWT Tokens (Recommended for Client Applications)

JWT tokens are short-lived (24 hours) and ideal for client-side applications. They can be refreshed using refresh tokens.

## Obtaining API Keys

### Creating an API Key

1. Log in to your [EcoEvents Dashboard](https://dashboard.ecoevents.com)
2. Navigate to **Settings** > **API Keys**
3. Click **Create New API Key**
4. Provide a descriptive name (e.g., "Production Server", "Staging Environment")
5. Select the appropriate permissions scope
6. Copy the key immediately (it won't be shown again)

<Note>
  API keys are displayed only once during creation. Store them securely in your environment variables or secrets manager. If you lose a key, you'll need to create a new one.
</Note>

### API Key Scopes

When creating an API key, you can limit its permissions:

| Scope             | Description                     |
| ----------------- | ------------------------------- |
| `events:read`     | Read event data                 |
| `events:write`    | Create and update events        |
| `events:delete`   | Delete events                   |
| `analytics:read`  | Access sustainability analytics |
| `vendors:read`    | View vendor information         |
| `vendors:write`   | Manage vendor relationships     |
| `webhooks:manage` | Configure webhooks              |
| `full_access`     | Complete account access         |

<Warning>
  Follow the principle of least privilege. Only grant the minimum permissions required for your application to function.
</Warning>

## Obtaining JWT Tokens

JWT tokens are obtained by authenticating with your account credentials:

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://api.ecoevents.com/v1/auth/login" \
    -H "Content-Type: application/json" \
    -d '{
      "email": "user@example.com",
      "password": "your_secure_password"
    }'
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch('https://api.ecoevents.com/v1/auth/login', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      email: 'user@example.com',
      password: 'your_secure_password'
    })
  });

  const { accessToken, refreshToken, expiresIn } = await response.json();

  // Store tokens securely
  localStorage.setItem('accessToken', accessToken);
  localStorage.setItem('refreshToken', refreshToken);
  ```

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

  response = requests.post(
      'https://api.ecoevents.com/v1/auth/login',
      json={
          'email': 'user@example.com',
          'password': 'your_secure_password'
      }
  )

  data = response.json()
  access_token = data['accessToken']
  refresh_token = data['refreshToken']

  # Store tokens securely (e.g., in environment variables)
  ```
</CodeGroup>

### Response

```json theme={null}
{
  "accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "refreshToken": "rt_1a2b3c4d5e6f7g8h9i0j",
  "expiresIn": 86400,
  "tokenType": "Bearer"
}
```

### Refreshing JWT Tokens

When your access token expires, use the refresh token to obtain a new one:

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://api.ecoevents.com/v1/auth/refresh" \
    -H "Content-Type: application/json" \
    -d '{
      "refreshToken": "rt_1a2b3c4d5e6f7g8h9i0j"
    }'
  ```

  ```javascript JavaScript theme={null}
  const refreshAccessToken = async () => {
    const refreshToken = localStorage.getItem('refreshToken');
    
    const response = await fetch('https://api.ecoevents.com/v1/auth/refresh', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({ refreshToken })
    });
    
    const { accessToken } = await response.json();
    localStorage.setItem('accessToken', accessToken);
    
    return accessToken;
  };
  ```

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

  def refresh_access_token(refresh_token):
      response = requests.post(
          'https://api.ecoevents.com/v1/auth/refresh',
          json={'refreshToken': refresh_token}
      )
      
      data = response.json()
      return data['accessToken']
  ```
</CodeGroup>

## Including Authentication in Requests

### Using API Keys

Include your API key in the `Authorization` header using the `Bearer` scheme:

<CodeGroup>
  ```bash cURL theme={null}
  curl -X GET "https://api.ecoevents.com/v1/events" \
    -H "Authorization: Bearer ek_live_1a2b3c4d5e6f7g8h9i0j"
  ```

  ```javascript JavaScript theme={null}
  const apiKey = process.env.ECOEVENTS_API_KEY;

  const response = await fetch('https://api.ecoevents.com/v1/events', {
    headers: {
      'Authorization': `Bearer ${apiKey}`,
      'Content-Type': 'application/json'
    }
  });

  const events = await response.json();
  ```

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

  api_key = os.getenv('ECOEVENTS_API_KEY')

  response = requests.get(
      'https://api.ecoevents.com/v1/events',
      headers={'Authorization': f'Bearer {api_key}'}
  )

  events = response.json()
  ```
</CodeGroup>

### Using JWT Tokens

JWT tokens are included in the same way as API keys:

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

  ```javascript JavaScript theme={null}
  const accessToken = localStorage.getItem('accessToken');

  const fetchWithAuth = async (url, options = {}) => {
    const response = await fetch(url, {
      ...options,
      headers: {
        'Authorization': `Bearer ${accessToken}`,
        'Content-Type': 'application/json',
        ...options.headers
      }
    });
    
    // Handle token expiration
    if (response.status === 401) {
      const newToken = await refreshAccessToken();
      // Retry request with new token
      return fetch(url, {
        ...options,
        headers: {
          'Authorization': `Bearer ${newToken}`,
          'Content-Type': 'application/json',
          ...options.headers
        }
      });
    }
    
    return response;
  };

  // Usage
  const response = await fetchWithAuth('https://api.ecoevents.com/v1/events');
  const events = await response.json();
  ```

  ```python Python theme={null}
  import requests
  from typing import Dict, Optional

  class EcoEventsClient:
      def __init__(self, access_token: str, refresh_token: str):
          self.access_token = access_token
          self.refresh_token = refresh_token
          self.base_url = 'https://api.ecoevents.com/v1'
      
      def _get_headers(self) -> Dict[str, str]:
          return {
              'Authorization': f'Bearer {self.access_token}',
              'Content-Type': 'application/json'
          }
      
      def _refresh_token(self):
          response = requests.post(
              f'{self.base_url}/auth/refresh',
              json={'refreshToken': self.refresh_token}
          )
          data = response.json()
          self.access_token = data['accessToken']
      
      def get(self, endpoint: str):
          response = requests.get(
              f'{self.base_url}/{endpoint}',
              headers=self._get_headers()
          )
          
          # Handle token expiration
          if response.status_code == 401:
              self._refresh_token()
              response = requests.get(
                  f'{self.base_url}/{endpoint}',
                  headers=self._get_headers()
              )
          
          return response.json()

  # Usage
  client = EcoEventsClient(access_token, refresh_token)
  events = client.get('events')
  ```
</CodeGroup>

## Testing API Keys

Test your API key by calling the authentication verification endpoint:

<CodeGroup>
  ```bash cURL theme={null}
  curl -X GET "https://api.ecoevents.com/v1/auth/verify" \
    -H "Authorization: Bearer YOUR_API_KEY"
  ```

  ```javascript JavaScript theme={null}
  const verifyApiKey = async (apiKey) => {
    const response = await fetch('https://api.ecoevents.com/v1/auth/verify', {
      headers: {
        'Authorization': `Bearer ${apiKey}`
      }
    });
    
    if (response.ok) {
      const data = await response.json();
      console.log('API key is valid:', data);
      return true;
    } else {
      console.error('API key is invalid');
      return false;
    }
  };
  ```

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

  def verify_api_key(api_key):
      response = requests.get(
          'https://api.ecoevents.com/v1/auth/verify',
          headers={'Authorization': f'Bearer {api_key}'}
      )
      
      if response.ok:
          print('API key is valid:', response.json())
          return True
      else:
          print('API key is invalid')
          return False
  ```
</CodeGroup>

### Success Response

```json theme={null}
{
  "valid": true,
  "key": {
    "id": "key_1a2b3c4d5e",
    "name": "Production Server",
    "scopes": ["events:read", "events:write", "analytics:read"],
    "createdAt": "2026-01-15T10:30:00Z",
    "lastUsed": "2026-03-05T14:22:00Z"
  },
  "account": {
    "id": "acc_9i8h7g6f5e",
    "name": "Green Events Co.",
    "tier": "professional"
  }
}
```

## Security Best Practices

### 1. Store Credentials Securely

<Warning>
  Never hardcode API keys or tokens in your source code. Use environment variables, secrets managers, or secure configuration files.
</Warning>

**Good Practice:**

```javascript theme={null}
// Use environment variables
const apiKey = process.env.ECOEVENTS_API_KEY;
```

**Bad Practice:**

```javascript theme={null}
// Never do this!
const apiKey = 'ek_live_1a2b3c4d5e6f7g8h9i0j';
```

### 2. Use HTTPS Only

Always use HTTPS for API requests. The EcoEvents API will reject plain HTTP requests.

### 3. Rotate Keys Regularly

Rotate your API keys periodically (e.g., every 90 days) and immediately if you suspect they've been compromised.

### 4. Use Appropriate Scopes

Grant only the minimum permissions required. If your application only reads events, use `events:read` instead of `full_access`.

### 5. Monitor API Key Usage

Regularly review API key usage in your dashboard. Revoke any keys that are no longer needed or show suspicious activity.

### 6. Implement Token Refresh Logic

For JWT-based authentication, implement automatic token refresh to handle expiration gracefully.

### 7. Handle Authentication Errors

Always handle `401 Unauthorized` responses appropriately:

```javascript theme={null}
const response = await fetch('https://api.ecoevents.com/v1/events', {
  headers: { 'Authorization': `Bearer ${apiKey}` }
});

if (response.status === 401) {
  console.error('Authentication failed. Check your API key.');
  // Handle re-authentication or notify user
}
```

### 8. Use Test Keys in Development

EcoEvents provides separate test API keys (prefixed with `ek_test_`) for development. These keys work with sandbox data and won't affect production.

<Note>
  Test API keys have the same format as live keys but are prefixed with `ek_test_` instead of `ek_live_`. Use them during development to avoid affecting production data.
</Note>

### 9. Implement Rate Limiting

Implement client-side rate limiting to stay within your tier's limits and avoid `429 Too Many Requests` errors.

### 10. Log Authentication Events

Log authentication attempts and failures for security monitoring and debugging.

## Revoking API Keys

If an API key is compromised or no longer needed:

1. Log in to your [EcoEvents Dashboard](https://dashboard.ecoevents.com)
2. Navigate to **Settings** > **API Keys**
3. Find the key you want to revoke
4. Click **Revoke** and confirm

<Warning>
  Revoking an API key immediately invalidates it. All requests using the revoked key will return `401 Unauthorized`. Update your applications before revoking keys currently in use.
</Warning>

## OAuth 2.0 (Coming Soon)

We're developing OAuth 2.0 support for third-party integrations. This will allow users to authorize your application without sharing their credentials.

Interested in beta access? Contact [api-support@ecoevents.com](mailto:api-support@ecoevents.com).

## Troubleshooting

### 401 Unauthorized

**Causes:**

* Invalid or expired API key
* Expired JWT token
* Missing `Authorization` header
* Incorrect authorization format

**Solution:**

* Verify your API key is correct
* Refresh your JWT token
* Ensure the header format is `Authorization: Bearer YOUR_KEY`

### 403 Forbidden

**Causes:**

* Insufficient permissions for the requested operation
* API key scope doesn't include required permission

**Solution:**

* Check the API key scopes in your dashboard
* Create a new key with appropriate permissions

### Token Refresh Fails

**Causes:**

* Refresh token expired (30 days)
* Refresh token already used
* Account password changed

**Solution:**

* Re-authenticate with username and password
* Obtain new access and refresh tokens

## Support

Need help with authentication? Contact our support team:

* **Email**: [api-support@ecoevents.com](mailto:api-support@ecoevents.com)
* **Documentation**: [https://docs.ecoevents.com/api/authentication](https://docs.ecoevents.com/api/authentication)
* **Security Issues**: [security@ecoevents.com](mailto:security@ecoevents.com)

<Note>
  For security vulnerabilities, please email [security@ecoevents.com](mailto:security@ecoevents.com) directly. We have a responsible disclosure program and typically respond within 24 hours.
</Note>
