Refresh Token
Exchange a refresh token for a new access token
Refresh Token
Exchange a refresh token for a new access token and refresh token pair. This endpoint does not require an access token in the Authorization header.
Endpoint
POST /refreshAuthentication
This endpoint does not require a Bearer token. Instead, you pass the refresh token in the request body.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
refresh_token | string | Yes | The refresh token from your last authentication or refresh |
Example Request
curl -X POST "https://edge.tiquo.app/api/client/v1/refresh" \
-H "Content-Type: application/json" \
-d '{
"refresh_token": "rt_xxx..."
}'Response
{
"success": true,
"data": {
"access_token": "eyJhbGciOiJSUzI1NiJ9...",
"refresh_token": "rt_new_xxx...",
"expires_in": 3600,
"expires_at": 1706580000000
}
}Response Fields
| Field | Type | Description |
|---|---|---|
access_token | string | New JWT access token (valid for 1 hour) |
refresh_token | string | New refresh token (valid for 30 days) |
expires_in | integer | Access token lifetime in seconds |
expires_at | integer | Access token expiration as a Unix timestamp in milliseconds |
Token Rotation
Refresh tokens are rotated on every use. Each time you call this endpoint, the old refresh token is revoked and a new one is issued. You must store and use the new refresh token from each response.
If you try to reuse an old refresh token that has already been consumed, the request will fail with a 401 error.
Token Lifetimes
| Token | Lifetime |
|---|---|
| Access token | 1 hour |
| Refresh token | 30 days |
Errors
| Status | Description |
|---|---|
400 | Missing refresh_token in the request body |
401 | Refresh token is invalid, expired, or has already been used |
500 | Internal server error |
Automatic Token Refresh
For browser-based applications using the DOM Package, token refresh is handled automatically. The SDK checks for token expiry and refreshes the access token 5 minutes before it expires, so you do not need to call this endpoint manually.
For custom integrations, you should implement your own refresh logic. Here is an example:
JavaScript
class TokenManager {
constructor(initialTokens) {
this.accessToken = initialTokens.access_token;
this.refreshToken = initialTokens.refresh_token;
this.expiresAt = initialTokens.expires_at;
}
async getValidToken() {
// Refresh if token expires in the next 5 minutes
const fiveMinutes = 5 * 60 * 1000;
if (Date.now() >= this.expiresAt - fiveMinutes) {
await this.refresh();
}
return this.accessToken;
}
async refresh() {
const response = await fetch(
'https://edge.tiquo.app/api/client/v1/refresh',
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ refresh_token: this.refreshToken }),
}
);
const { success, data, error } = await response.json();
if (!success) {
throw new Error(`Token refresh failed: ${error}`);
}
this.accessToken = data.access_token;
this.refreshToken = data.refresh_token;
this.expiresAt = data.expires_at;
}
}Swift
func refreshTokens(refreshToken: String) async throws -> TokenPair {
var request = URLRequest(url: URL(string: "https://edge.tiquo.app/api/client/v1/refresh")!)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try JSONEncoder().encode(["refresh_token": refreshToken])
let (data, _) = try await URLSession.shared.data(for: request)
let result = try JSONDecoder().decode(RefreshResponse.self, from: data)
return result.data
}