All AdvanGuard API requests require a valid JWT access token. This guide explains how to obtain and use tokens.
Overview
AdvanGuard uses a two-step authentication flow:
- Generate a token — call
POST /v1/auth/tokenswith youraccessKeyand a cryptographicsignatureto receive a JWT access token. - Use the token — include the token in the
Authorizationheader of every subsequent API request.
Credentials
Each tenant account is issued a pair of credentials:
| Credential | Description |
|---|---|
accessKey | Public identifier for your account |
secretKey | Secret used to compute the request signature. Never transmit this value. |
Obtain your accessKey and secretKey from the AdvanGuard platform under Account → Account Management.
Generating an Access Token
Compute the Signature
The signature proves you hold the secretKey without transmitting it over the network.
- Concatenate three values into a single string:
accessKey + secretKey + timestamp - Compute the SHA-256 hash of the concatenated string
- The resulting lowercase hex string is your
signature
Example:
| Value | Content |
|---|---|
| accessKey | sampleaccesskey |
| secretKey | samplesecretkey |
| timestamp | 1665993522952 |
| Concatenated | sampleaccesskeysamplesecretkey1665993522952 |
| SHA-256 signature | 02209bbeaf0d0a3dd587f6a1ba22f84c98d142e3b545e77db7e4906ca56349f5 |
Important: The
timestampin the signature must be identical to thetimestampparameter in the request body.
Java
import java.security.MessageDigest;
public class SignatureUtil {
public static String computeSignature(String accessKey, String secretKey, String timestamp) {
try {
String combined = accessKey + secretKey + timestamp;
MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] hash = digest.digest(combined.getBytes("UTF-8"));
StringBuilder hex = new StringBuilder();
for (byte b : hash) {
String h = Integer.toHexString(0xff & b);
if (h.length() == 1) hex.append('0');
hex.append(h);
}
return hex.toString();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}Python
import hashlib
import time
def compute_signature(access_key: str, secret_key: str, timestamp: str) -> str:
combined = access_key + secret_key + timestamp
return hashlib.sha256(combined.encode("utf-8")).hexdigest()Node.js
const crypto = require("crypto");
function computeSignature(accessKey, secretKey, timestamp) {
const combined = accessKey + secretKey + timestamp;
return crypto.createHash("sha256").update(combined, "utf8").digest("hex");
}Request a Token
curl -X POST https://openapi.advance.ai/v1/auth/tokens \
-H "Content-Type: application/json" \
-d '{
"accessKey": "22ab70b",
"timestamp": 1718524800000,
"signature": "f786441e7b3d95f853a5a244f9522",
"expiresIn": 3600
}'Response (200 OK):
{
"accessToken": "eyJhbGciOiJIUzUxMiJ9.eyJpc3MiOiJhZHZhbmd1YXJkIn0.abc123",
"tokenType": "Bearer",
"expiresIn": 3600,
"expiresAt": "2026-06-16T10:00:00Z"
}Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
accessKey | string | Yes | Your access key |
timestamp | integer | Yes | 13-digit Unix timestamp in milliseconds |
signature | string | Yes | SHA-256 hash of accessKey + secretKey + timestamp |
expiresIn | integer | No | Token validity in seconds (default 3600, min 60, max 86400) |
Using the Token
Include the access token in the Authorization header using the Bearer scheme:
Authorization: Bearer <access_token>
Example:
curl https://openapi.advance.ai/v1/individual/applications \
-H "Authorization: Bearer eyJhbGciOiJIUzUxMiJ9..."Token Lifecycle
- Generate — call
POST /v1/auth/tokensto obtain a token. - Use — include the token in every API request's
Authorizationheader. - Expires — the token becomes invalid after the
expiresInperiod. The API returns401withauthentication_error. - Regenerate — request a new token before or after the current one expires.
Tip: Track the
expiresAtvalue and proactively generate a new token before expiration to avoid request failures.
Security Requirements
- HTTPS only: All requests must use HTTPS. HTTP requests are rejected.
- Never expose your
secretKey: Do not include it in client-side code, URLs, or version control. - Keep tokens short-lived: Use the shortest practical
expiresInvalue for your use case. - Do not hardcode tokens: Tokens expire; always generate them programmatically.
Gateway Headers
After successful authentication, the API gateway injects the following headers into downstream requests:
| Header | Description |
|---|---|
X-Account-Id | Tenant account ID |
X-Organization-Id | Customer organization ID |
X-Request-Id | Unique request trace ID (also returned in responses) |
You do not need to send accountId or customerId in request bodies — these are derived from your access token automatically.
Rate Limiting
Each account has rate limits applied. When exceeded, the API returns 429 Too Many Requests:
{
"error": {
"type": "rate_limit_error",
"message": "Too many requests. Please retry after 60 seconds"
}
}The Retry-After response header indicates when you can retry.
Error Responses
| HTTP Status | Error Type | Meaning |
|---|---|---|
| 400 | invalid_request_error | Missing or invalid parameters (e.g., bad timestamp) |
| 401 | authentication_error | Token is missing, invalid, expired, or signature verification failed |
| 403 | authentication_error | Account has been disabled |
| 429 | rate_limit_error | Rate limit exceeded |
Best Practices
- Store your
secretKeyin environment variables or a secrets manager, never in code. - Generate tokens programmatically and cache them until near expiration.
- Use short-lived tokens (e.g., 1 hour) to limit exposure if a token is compromised.
- Monitor usage and set up alerts for unusual traffic patterns.
- Use a testing account during development to avoid affecting production data.