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:

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

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');

Last updated

Was this helpful?