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?