# Authentication

Bead supports multiple authentication methods depending on the API family you are calling.

For current integrations:

* **Payments API** uses an API key sent in the `X-Api-Key` header
* **Onboarding API** uses an API key sent in the `X-Api-Key` header
* **Other Bead APIs** may use OAuth 2.0 Bearer tokens depending on the product area and endpoint family
* **Legacy Payments integrations** may still use OAuth 2.0 password grant with the `bead-terminal` client

If you are unsure which authentication method applies to your use case, ask your Bead contact.

### When to use each authentication method

* **Payments API**: use an API key in the `X-Api-Key` header for new integrations
* **Onboarding API**: use an API key in the `X-Api-Key` header
* **Other Bead APIs**: follow the authentication requirements documented for that API family or endpoint
* **Legacy Payments integrations**: OAuth 2.0 password grant remains supported where already in use

### Payments authentication (preferred): API key

A Payments API key is the secret credential used to authenticate Payments requests. You must send the full API key value on each request in the `X-Api-Key` header.

The masked API key is a display value only and cannot be used to authenticate.

#### Required request header

```http
X-Api-Key: {apiKey}
```

For JSON requests, also send:

```http
Content-Type: application/json
```

#### Example curl (Payments)

```bash
curl -s -X POST "{BASE_URL}/Payments/crypto" \
  -H "Content-Type: application/json" \
  -H "X-Api-Key: {apiKey}" \
  -d '{
    "merchantId": "{merchantId}",
    "terminalId": "{terminalId}",
    "requestedAmount": 25.00,
    "reference": "ORDER123"
  }'
```

#### Payments API key notes

* Treat the API key like a password
* Store it in a secret manager or environment variable
* Do not log the full value
* If you believe an API key is exposed, rotate it immediately through your Bead contact

#### Payments troubleshooting

* `401 Unauthorized`: the API key is missing, invalid, or sent using the wrong header name. The header must be exactly `X-Api-Key`.
* If you try OAuth flows such as `client_credentials` for `POST /Payments/crypto`, you may see errors like `Public client not allowed to retrieve service account`. Payments authentication for that endpoint uses `X-Api-Key`.

### Onboarding authentication: API key

Onboarding requests use an API key sent in the `X-Api-Key` header.

#### Required request header

```http
X-Api-Key: {apiKey}
```

For JSON requests, also send:

```http
Content-Type: application/json
Accept: application/json
```

#### Current onboarding request guidance

Use the API key header model for onboarding requests.

Do not send deprecated `apiKey` fields in onboarding request bodies.

For the current onboarding request model:

* **Full application** requests use `signer` and `merchantData`
* **Minimal application** requests use `signerName` and `signerEmail`
* Onboarding create requests require `cryptoEnvironment`

#### Current onboarding create endpoints

```http
POST /merchant-onboarding/applications
POST /merchant-onboarding/applications-short
```

#### Onboarding environment note

For onboarding create requests, set `cryptoEnvironment` to match the environment you are targeting:

* `sandbox` in Sandbox
* `production` in Production

#### Transition note

Legacy bearer-token authentication may still work in some environments during migration, but new integrations should use API key authentication consistently across the Onboarding APIs.

### Payments authentication (legacy): OAuth password grant (`bead-terminal`)

Existing integrators may continue to authenticate Payments using OAuth 2.0 password grant with a terminal username and password. New Payments integrations should use the API key method above.

#### Password grant request fields

* `grant_type=password`
* `client_id=bead-terminal`
* `username`
* `password`

#### Example curl (legacy Payments)

```bash
curl -s -X POST "{identity_base_url}/realms/{realm}/protocol/openid-connect/token" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=password" \
  -d "client_id=bead-terminal" \
  -d "username={username}" \
  -d "password={password}"
```

### OAuth token endpoint (OpenID Connect)

OAuth access tokens are used by Bead APIs and endpoints that require OAuth authentication. The same token endpoint format and realms are also used for legacy Payments integrations.

#### Endpoint format

```http
POST {identity_base_url}/realms/{realm}/protocol/openid-connect/token
```

#### Required header

```http
Content-Type: application/x-www-form-urlencoded
```

#### Placeholders

* `identity_base_url`: typically `https://identity.beadpay.io`
* `realm`: environment realm
  * `nonprod` for Sandbox and other non-production environments
  * `prod` for Production

#### Common token URL examples

```
https://identity.beadpay.io/realms/nonprod/protocol/openid-connect/token
https://identity.beadpay.io/realms/prod/protocol/openid-connect/token
```

### Typical token response (OAuth)

A successful token request returns a JSON object that includes fields such as:

* `access_token`
* `expires_in`
* `refresh_token`
* `refresh_expires_in`
* `token_type` set to `Bearer`

Store tokens securely and avoid logging full token values in plain text.

### Refresh token request (OAuth)

Use the refresh token grant to obtain a new access token without prompting for credentials again.

#### Fields

* `grant_type=refresh_token`
* `client_id={client_id}`
* `refresh_token={refresh_token}`

#### Example curl

```bash
curl -s -X POST "{identity_base_url}/realms/{realm}/protocol/openid-connect/token" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=refresh_token" \
  -d "client_id={client_id}" \
  -d "refresh_token={refresh_token}"
```

### Using an OAuth access token

Add the access token as an `Authorization` header on every request to APIs that require OAuth authentication.

```http
Authorization: Bearer {access_token}
```

### Optional scopes (OAuth)

Scopes are not required for core API calls.

* Include `scope=openid` only if you need an ID token or plan to call a user info endpoint
* Include `profile` or `email` only if you consume those claims in a portal or user-facing application
* If you do not need identity claims, omit the `scope` parameter and treat the token as a pure API access token

### Quick troubleshooting summary

#### API key requests

* Confirm the header name is exactly `X-Api-Key`
* Confirm you are using the full API key value
* Confirm the key matches the correct environment
* Do not send masked keys or deprecated body fields

#### Onboarding requests

* Use API key auth
* Use the current request shapes, not `signerInfo`
* Set `cryptoEnvironment` correctly
* Keep environment and credentials aligned

#### OAuth requests

* Verify realm selection: `nonprod` vs `prod`
* Verify client and grant type
* Verify access token freshness
* Send the token as `Authorization: Bearer {access_token}`
