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

# Nexenergie API Authentication — Tokens and API Keys

> Reference for the POST /auth/token endpoint and the Authorization header required on every Nexenergie API request. Covers token expiry and API keys.

All Nexenergie API requests must include a valid credential in the `Authorization` header. You can authenticate with a short-lived token — valid for 24 hours and obtained by exchanging your email and password — or with a long-lived API key generated from your account dashboard. Both credential types are passed identically as Bearer tokens once issued.

## POST /auth/token

Exchange your account email and password for a Bearer token. This endpoint expects a form-encoded request body.

**`POST /auth/token`**

### Request

The request body must be encoded as `application/x-www-form-urlencoded`.

<ParamField body="username" type="string" required>
  Your Nexenergie account email address (e.g., `user@example.com`).
</ParamField>

<ParamField body="password" type="string" required>
  The password associated with your Nexenergie account.
</ParamField>

<CodeGroup>
  ```bash cURL theme={null}
  curl --request POST \
    --url https://app.nexenergie.ai/api/v1/auth/token \
    --header 'Content-Type: application/x-www-form-urlencoded' \
    --data 'username=user@example.com' \
    --data 'password=your-password'
  ```

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

  response = httpx.post(
      "https://app.nexenergie.ai/api/v1/auth/token",
      data={
          "username": "user@example.com",
          "password": "your-password",
      },
  )
  token_data = response.json()
  access_token = token_data["access_token"]
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch(
    "https://app.nexenergie.ai/api/v1/auth/token",
    {
      method: "POST",
      headers: { "Content-Type": "application/x-www-form-urlencoded" },
      body: new URLSearchParams({
        username: "user@example.com",
        password: "your-password",
      }),
    }
  );
  const { access_token } = await response.json();
  ```
</CodeGroup>

### Response

A successful `200 OK` response returns the following JSON body:

<ResponseField name="access_token" type="string">
  The Bearer token to include in the `Authorization` header of all subsequent API requests.
</ResponseField>

<ResponseField name="token_type" type="string">
  Always `"bearer"`. Indicates how the token should be presented in the header.
</ResponseField>

<ResponseField name="expires_in" type="integer">
  Lifetime of the token in seconds. The default value is `86400` (24 hours), after which the token is no longer valid and a new one must be requested.
</ResponseField>

```json Example Response theme={null}
{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VyQGV4YW1wbGUuY29tIiwiZXhwIjoxNzMyMTg2NDAwfQ.abc123xyz",
  "token_type": "bearer",
  "expires_in": 86400
}
```

## Authorization Header

Once you have a token, pass it in the `Authorization` header on every subsequent request:

```text theme={null}
Authorization: Bearer <token>
```

<CodeGroup>
  ```bash cURL theme={null}
  curl --request GET \
    --url https://app.nexenergie.ai/api/v1/forecasts/day-ahead \
    --header 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'
  ```

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

  headers = {"Authorization": f"Bearer {access_token}"}

  response = httpx.get(
      "https://app.nexenergie.ai/api/v1/forecasts/day-ahead",
      headers=headers,
  )
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch(
    "https://app.nexenergie.ai/api/v1/forecasts/day-ahead",
    {
      headers: { Authorization: `Bearer ${accessToken}` },
    }
  );
  ```
</CodeGroup>

## API Keys

API keys are long-lived credentials that you generate directly from your Nexenergie account dashboard under [API Keys settings](/account/api-keys). They are suitable for server-side integrations, automated pipelines, and any context where re-authenticating with a username and password would be impractical.

API keys are used **identically** to short-lived tokens — pass them as the Bearer value in the `Authorization` header:

```text theme={null}
Authorization: Bearer nxe_live_sk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
```

Unlike tokens obtained from `POST /auth/token`, API keys **do not expire** based on time. They remain valid until you explicitly revoke them from the dashboard. You can create multiple keys with descriptive labels to identify which integration each key belongs to, and rotate or revoke them individually without affecting other keys.

<Tip>
  Use separate API keys for each environment (development, staging, production) and each integration. This lets you rotate or revoke a single key without disrupting other services.
</Tip>

## Token Expiry

Tokens issued by `POST /auth/token` expire after **86400 seconds (24 hours)**. Requests made with an expired token return `401 Unauthorized`. Your integration should detect expiry and re-authenticate before continuing.

The following Python example shows a simple retry-with-refresh pattern:

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

TOKEN_URL = "https://app.nexenergie.ai/api/v1/auth/token"
API_BASE  = "https://app.nexenergie.ai/api/v1"

class NexenergieClient:
    def __init__(self, username: str, password: str):
        self.username = username
        self.password = password
        self._token: str | None = None
        self._token_expiry: float = 0.0

    def _authenticate(self) -> None:
        response = httpx.post(
            TOKEN_URL,
            data={"username": self.username, "password": self.password},
        )
        response.raise_for_status()
        data = response.json()
        self._token = data["access_token"]
        # Refresh 60 seconds before actual expiry to avoid edge-case failures
        self._token_expiry = time.time() + data["expires_in"] - 60

    def _get_headers(self) -> dict:
        if self._token is None or time.time() >= self._token_expiry:
            self._authenticate()
        return {"Authorization": f"Bearer {self._token}"}

    def get(self, path: str, **kwargs) -> httpx.Response:
        response = httpx.get(
            f"{API_BASE}{path}",
            headers=self._get_headers(),
            **kwargs,
        )
        if response.status_code == 401:
            # Token may have been invalidated server-side; force refresh once
            self._token = None
            response = httpx.get(
                f"{API_BASE}{path}",
                headers=self._get_headers(),
                **kwargs,
            )
        response.raise_for_status()
        return response


# Usage
client = NexenergieClient("user@example.com", "your-password")
forecast = client.get("/forecasts/day-ahead").json()
```

<Warning>
  Never log, print, or embed tokens or API keys in client-side code, version control, or publicly accessible configuration files. Anyone who obtains your credential can make API calls charged against your account and access your organisation's forecast data. Use environment variables or a secrets manager to store credentials securely.
</Warning>
