> For the complete documentation index, see [llms.txt](https://docs.gameket.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.gameket.io/introduction/authentication.md).

# Authentication

Gameket uses JWT-based Bearer token authentication for merchant API access. This guide explains how to authenticate and manage tokens.

### Token Generation

To get a Bearer token, POST your API credentials to the authentication endpoint.

**Endpoint:**

```bash
POST /merchant/auth/check
```

**Request Body:**

```json
{
  "apiKey": "your_merchant_api_key",
  "secret": "your_merchant_secret"
}
```

**Response:**

```json
{
  "success": true,
  "data": {
    "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
    "tokenType": "Bearer",
    "expiresInSeconds": 7200,
    "expiresAt": "2026-05-10T17:10:31.000Z",
    "merchant": {
      "storeId": "store_abc123",
      "storeName": "My Store"
    }
  }
}
```

**Rate Limit:**

* **2 tokens per hour** per merchant
* Helps prevent token abuse and maintains security

### Using Bearer Tokens

Include the token in the `Authorization` header of all protected requests:

```bash
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
```

**Required headers for protected endpoints:**

```
Authorization: Bearer {token}
x-merchant-api-key: {your_api_key}
```

**For write operations, also include:**

```
Idempotency-Key: {unique-key-per-request}
```

#### Example Protected Request

```bash
curl -X GET "https://api.gameket.io/merchant/orders?page=1&limit=20" \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." \
  -H "x-merchant-api-key: your_merchant_api_key"
```

### Token Expiry & Refresh

Tokens are valid for **2 hours** (7200 seconds). When a token expires:

1. The API returns `401 Unauthorized`
2. Request a new token using the same endpoint
3. Use the new token for subsequent requests

**Recommended Token Refresh Strategy:**

```javascript
// Refresh token every 90 minutes (before expiry)
setInterval(async () => {
  const response = await fetch('https://api.gameket.io/merchant/auth/check', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      apiKey: process.env.MERCHANT_API_KEY,
      secret: process.env.MERCHANT_SECRET
    })
  });
  
  const { data } = await response.json();
  store.token = data.token;
  store.tokenExpiresAt = new Date(data.expiresAt);
}, 90 * 60 * 1000); // 90 minutes
```
