# Authentication

Partner APIs require [OAuth2](https://oauth.net/) client credentials. You authenticate by exchanging a Client ID and Secret for a short-lived JWT access token, then sending that token in the `Authorization` header.

:::note
All Entur APIs, open and partner, also require the `ET-Client-Name` header on every request. See [**Client identification**](/docs/getting-started#client-identification-et-client-name).
:::

## Setup

### 1. Create client credentials

1. Go to [Entur Partner](https://entur-partner.entur.org/permission-admin/clients/create) and create a client
2. View the created client and note the **Client ID** and **Client secret**
2. Be sure to store the **Client secret** securely.

:::note

Only users with the role [**Brukeradministrator**](https://entur-partner.entur.org/permission-admin/roles/view/35) in your organization can create clients.

:::

### 2. Get an access token

Call the authentication service that matches the environment where your client was created. Use the `client_credentials` grant type.

| Environment | Authentication service endpoint   | Audience                     |
|-------------|-----------------------------------|------------------------------|
| Production  | https://partner.entur.org         | https://api.entur.io         |
| Staging     | https://partner.staging.entur.org | https://api.staging.entur.io |
| Dev         | https://partner.dev.entur.org     | https://api.dev.entur.io     |

**Request body**

```json
{
  "client_id": "YOUR_CLIENT_ID",
  "client_secret": "YOUR_CLIENT_SECRET",
  "audience": "https://api.entur.io",
  "grant_type": "client_credentials"
}
```

**Example request (production)**

```sh
curl --request POST \
  --url https://partner.entur.org/oauth/token \
  --header 'content-type: application/json' \
  --data '{
    "client_id": "YOUR_CLIENT_ID",
    "client_secret": "YOUR_CLIENT_SECRET",
    "audience": "https://api.entur.io",
    "grant_type": "client_credentials"
  }'
```

We recommend using established [OAuth2 libraries](https://oauth.net/code/) instead of building this flow from scratch.

### 3. Use the access token

Include the JWT access token in the `Authorization` header for every Partner API request:

```http
Authorization: Bearer <ACCESS_TOKEN>
```

**Example request**

```sh
curl --request GET \
  --url "https://api.entur.io/personalisation/v1/programs/1" \
  --header "Authorization: Bearer <ACCESS_TOKEN>"
```

### 4. Cache and expiry

- Cache access tokens securely and reuse them until they expire.
- Tokens from Entur’s authentication service are valid for **24 hours**.
- You can track expiry via the `expires_in` field from the token response or the `exp` claim inside the JWT.

Requests using expired tokens will return HTTP 401.

## Troubleshooting

Common HTTP status codes during authentication:

- **401 Unauthorized** – Missing/invalid `client_secret`, missing token, or expired token.
- **403 Forbidden** – The token is valid, but lacks required permissions for the endpoint.
- **408 Session timeout** – The token expired during processing; obtain a new token.
