> 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/examples/thunder-client.md).

# Thunder Client

1. **Create Environment**
   * Variable: `base_url` = `https://api.gameket.io`
   * Variable: `token` = (will be set by requests)
   * Variable: `apiKey` = `mapi_abc123def456`
2. **Token Request**

   ```bash
   POST {{base_url}}/merchant/auth/check
   Body: { "apiKey": "...", "secret": "..." }
   Test: Set token variable
   ```
3. **Authenticated Requests**

   ```bash
   GET {{base_url}}/merchant
   Headers: 
   - Authorization: Bearer {{token}}
   - x-merchant-api-key: {{apiKey}}
   ```

### Monitoring & Logging

{% code expandable="true" %}

```javascript
class MerchantAPILogger {
  log(method, endpoint, status, duration, requestId) {
    const timestamp = new Date().toISOString();
    console.log(JSON.stringify({
      timestamp,
      method,
      endpoint,
      status,
      duration: `${duration}ms`,
      requestId
    }));
  }

  error(error, context) {
    const timestamp = new Date().toISOString();
    console.error(JSON.stringify({
      timestamp,
      level: 'error',
      error: error.message,
      code: error.code,
      context
    }));
  }
}

// Wrap requests with logging
async function loggedRequest(method, endpoint, body, logger) {
  const startTime = Date.now();
  try {
    const response = await fetch(`https://api.gameket.io${endpoint}`, {
      method,
      headers: { /* ... */ },
      body: body ? JSON.stringify(body) : null
    });

    const duration = Date.now() - startTime;
    const requestId = response.headers.get('request-id');
    logger.log(method, endpoint, response.status, duration, requestId);

    return response.json();
  } catch (error) {
    logger.error(error, { method, endpoint });
    throw error;
  }
}
```

{% endcode %}
