# Token Refresh Management

Auth tokens expire after a set time period. Use your refresh token to obtain new auth tokens without re-entering your login credentials. Always refresh your token before it expires to maintain uninterrupted API access.

#### Refreshing Tokens

**Endpoint**: `GET /auth/token`

**Required Headers**:

```http
X-Violet-App-Id: your-app-id-here
X-Violet-App-Secret: your-app-secret-here
X-Violet-Token: your-refresh-token-here
Content-Type: application/json
```

#### Example Automatic Token Refresh Implementation

```javascript
class VioletAuthManager {
  constructor(appId, appSecret, username, password) {
    this.appId = appId;
    this.appSecret = appSecret;
    this.username = username;
    this.password = password;
    this.authToken = null;
    this.refreshToken = null;
    this.expiresAt = null;
    this.baseURL = 'https://sandbox-api.violet.io/v1';
  }

  async initialize() {
    const tokens = await this.login();
    this.setTokens(tokens);
    return tokens;
  }

  async login() {
    const response = await fetch(`${this.baseURL}/login`, {
      method: 'POST',
      headers: {
        'X-Violet-App-Id': this.appId,
        'X-Violet-App-Secret': this.appSecret,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        username: this.username,
        password: this.password
      })
    });

    if (!response.ok) {
      const errorData = await response.json();
      throw new Error(errorData.message || 'Login failed');
    }

    const data = await response.json();

    return {
      authToken: data.token,
      refreshToken: data.refresh_token,
      expiresAt: new Date(data.expires_at)
    };
  }

  async refreshAuthToken() {
    if (!this.refreshToken) {
      throw new Error('No refresh token available. Please re-authenticate.');
    }

    try {
      const response = await fetch(`${this.baseURL}/auth/token`, {
        headers: {
          'X-Violet-App-Id': this.appId,
          'X-Violet-App-Secret': this.appSecret,
          'X-Violet-Token': this.refreshToken,
          'Content-Type': 'application/json'
        }
      });

      if (!response.ok) {
        throw new Error('Token refresh failed');
      }

      const data = await response.json();
      this.authToken = data.token;
      this.expiresAt = this.extractExpiryFromJWT(data.token);
      
      return this.authToken;
    } catch (error) {
      // If refresh fails, re-authenticate
      console.warn('Token refresh failed, re-authenticating...');
      const tokens = await this.login();
      this.setTokens(tokens);
      return this.authToken;
    }
  }

  async getValidToken() {
    // Check if token is expired or will expire within 5 minutes
    const now = new Date();
    const fiveMinutesFromNow = new Date(now.getTime() + 5 * 60 * 1000);

    if (!this.authToken || !this.expiresAt || this.expiresAt <= fiveMinutesFromNow) {
      await this.refreshAuthToken();
    }

    return this.authToken;
  }

  async makeRequest(endpoint, method = 'GET', data = null) {
    const token = await this.getValidToken();
    
    const url = `${this.baseURL}${endpoint}`;
    const options = {
      method,
      headers: {
        'X-Violet-App-Id': this.appId,
        'X-Violet-App-Secret': this.appSecret,
        'X-Violet-Token': token,
        'Content-Type': 'application/json'
      }
    };

    if (data && ['POST', 'PUT', 'PATCH'].includes(method)) {
      options.body = JSON.stringify(data);
    }

    try {
      let response = await fetch(url, options);

      if (response.status === 401) {
        // Token might be expired, try refreshing once
        await this.refreshAuthToken();
        options.headers['X-Violet-Token'] = this.authToken;
        response = await fetch(url, options);
      }

      if (!response.ok) {
        const errorData = await response.json();
        throw new Error(errorData.message || 'API request failed');
      }

      return response.json();
  }

  setTokens({ authToken, refreshToken, expiresAt }) {
    this.authToken = authToken;
    this.refreshToken = refreshToken;
    this.expiresAt = expiresAt;
  }

  extractExpiryFromJWT(token) {
    try {
      const payload = JSON.parse(atob(token.split('.')[1]));
      return new Date(payload.exp * 1000);
    } catch (error) {
      console.warn('Failed to extract expiry from JWT:', error);
      return new Date(Date.now() + 24 * 60 * 60 * 1000); // Default to 24 hours
    }
  }
}

// Usage example
const authManager = new VioletAuthManager(
  process.env.VIOLET_APP_ID,
  process.env.VIOLET_APP_SECRET,
  process.env.VIOLET_USERNAME,
  process.env.VIOLET_PASSWORD
);

await authManager.initialize();

// Make authenticated requests
const merchants = await authManager.makeRequest('/merchants');
const orders = await authManager.makeRequest('/orders');
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.violet.io/concepts/overview/token-refresh-management.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
