Authentication Overview
The Vertex Play API uses a multi-layered Authentication mechanism to ensure the security of API requests.
● API KEY is used for all API encryption and decryption processes (this page's process)
● Secret KEY is mainly used for the "Get Access Token" /v2/auth API (this value is not related to the content on this page)
● API KEY Specification Description.
Format: 64-bit lowercase Hex, no spaces/newlines.
Characters: 0-9 and a-f only.
Example: ed7e50...941020ad (64 characters in total).
Error prevention: When copying, leading/trailing spaces must be removed.
Authentication Flow
request Headers
All API requests must include the following headers:
Auth Request (/v2/auth)
| Header | Type | Required | Description |
|---|---|---|---|
Content-Type | string | Yes | Must be application/json |
x-agentid | string | Yes | Agent ID |
x-timestamp | string | Yes | Unix timestamp (milliseconds) |
x-nonce | string | Yes | 32-character random string (for replay attack prevention) |
x-signature | string | Yes | SHA256 signature |
Other API Requests
| Header | Type | Required | Description |
|---|---|---|---|
Authorization | string | Yes | Bearer token, format: Bearer {accessToken} |
Content-Type | string | Yes | Must be application/json |
x-agentid | string | Yes | Agent ID |
x-timestamp | string | Yes | Unix timestamp (milliseconds) |
x-nonce | string | Yes | 32-character random string |
x-signature | string | Yes | SHA256 signature |
Signature Generation
The signature is generated using the SHA256 algorithm to ensure the integrity and authenticity of the request.
Signature Steps
-
Prepare signature string: Concatenate the following parameters in order
agentId + '|' + timestamp + '|' + nonce + '|' + cipherText -
Generate signature: Use SHA256 algorithm
signature = SHA256(signatureString) -
Add to request header: Place the generated signature into the
x-signatureheader
Node.js Example
const crypto = require('crypto');
function generateSignature(agentId, timestamp, nonce, cipherText) {
// Concatenate signature string
const signatureString = `${agentId}|${timestamp}|${nonce}|${cipherText}`;
// Generate SHA256 signature
const signature = crypto
.createHash('sha256')
.update(signatureString)
.digest('hex');
return signature;
}
// Usage example
const agentId = 'integratorNBTest04';
const timestamp = Date.now().toString();
const nonce = crypto.randomBytes(16).toString('hex');
const requestBody = {
cipherText: 'G0ZMDELeJwx+7JcIfIFO...'
};
const signature = generateSignature(agentId, timestamp, nonce, cipherText);
Python Example
import hashlib
import json
import time
import secrets
def generate_signature(agent_id, timestamp, nonce, cipherText):
# Concatenate signature string
signature_string = f"{agent_id}|{timestamp}|{nonce}|{cipherText}"
# Generate SHA256 signature
signature = hashlib.sha256(
signature_string.encode('utf-8')
).hexdigest()
return signature
# Usage example
agent_id = 'integratorNBTest04'
timestamp = str(int(time.time() * 1000))
nonce = secrets.token_hex(16)
request_body = {
'cipherText': 'G0ZMDELeJwx+7JcIfIFO...'
}
signature = generate_signature(agent_id, timestamp, nonce, cipherText)
Data Encryption
All sensitive data in requests use AES-256-GCM encryption, and responses are in plain JSON format.
Encryption Format
{
"cipherText": "ivBase64 (16 characters) + authTagBase64 (24 characters) + encryptedDataBase64"
}
Encryption Parameters
- Algorithm: AES-256-GCM
- Key Length: 256 bits (32 bytes)
- IV Length: 96 bits (12 bytes)
- Authentication Tag Length: 128 bits (16 bytes)
cipherText Structure
cipherText consists of three parts, all base64 encoded:
-
IV (Initialization Vector)
- Length: 12 bytes
- After Base64 encoding: 16 characters
- Position:
cipherText[0:16]
-
Auth Tag (Authentication tag)
- Length: 16 bytes
- After Base64 encoding: 24 characters
- Position:
cipherText[16:40]
-
Encrypted Data (Encrypted data)
- Length: Variable, depends on original data
- Base64 encoded
- Position:
cipherText[40:]
Decryption Example (Node.js)
const crypto = require('crypto');
const AES_ALGORITHM = 'aes-256-gcm';
/**
* Decrypt cipherText
* @param {string} key - AES key (hex format)
* @param {string} cipherText - Encrypted text
* @returns {Object} - Decrypted JSON object
*/
function symmetricDecrypt(key, cipherText) {
try {
const aesKey = Buffer.from(key, 'hex');
// Separate iv, authTag, and encrypted data from ciphertext
const ivLength = 16; // base64 encoded 12 bytes
const authTagLength = 24; // base64 encoded 16 bytes
const ivBase64 = cipherText.substring(0, ivLength);
const authTagBase64 = cipherText.substring(ivLength, ivLength + authTagLength);
const encryptedData = cipherText.substring(ivLength + authTagLength);
const aesIv = Buffer.from(ivBase64, 'base64');
const authTag = Buffer.from(authTagBase64, 'base64');
// Create decipher
const decipher = crypto.createDecipheriv(AES_ALGORITHM, aesKey, aesIv);
decipher.setAuthTag(authTag); // Set Authentication tag, GCM will automatically verify integrity
// Decrypt
let decrypted = decipher.update(encryptedData, 'base64', 'utf8');
decrypted += decipher.final('utf8'); // If authTag verification fails, an error will be thrown here
return JSON.parse(decrypted);
} catch (e) {
throw new Error(`Symmetric Decryption Failed: ${e.message}`);
}
}
// Usage example
const key = 'your-32-byte-hex-key'; // 64 hex characters = 32 bytes
const cipherText = 'G0ZMDELeJwx+7JcI...'; // complete cipherText
try {
const decryptedData = symmetricDecrypt(key, cipherText);
console.log('Decrypted data:', decryptedData);
} catch (error) {
console.error('Decryption error:', error.message);
}
Encryption Example (Node.js)
/**
* Encrypt data
* @param {string} key - AES key (hex format)
* @param {Object} data - JSON object to encrypt
* @returns {string} - Encrypted cipherText
*/
function symmetricEncrypt(key, data) {
try {
const aesKey = Buffer.from(key, 'hex');
// Generate random IV (12 bytes)
const aesIv = crypto.randomBytes(12);
// Create cipher
const cipher = crypto.createCipheriv(AES_ALGORITHM, aesKey, aesIv);
// Encrypt data
const jsonString = JSON.stringify(data);
let encrypted = cipher.update(jsonString, 'utf8', 'base64');
encrypted += cipher.final('base64');
// Get Authentication tag (16 bytes)
const authTag = cipher.getAuthTag();
// Combine cipherText: ivBase64 + authTagBase64 + encryptedData
const cipherText = aesIv.toString('base64') +
authTag.toString('base64') +
encrypted;
return cipherText;
} catch (e) {
throw new Error(`Symmetric Encryption Failed: ${e.message}`);
}
}
// Usage example
const data = {
username: 'player001',
amount: 100
};
const cipherText = symmetricEncrypt(key, data);
console.log('Encrypted cipherText:', cipherText);
Error Handling
Authentication Error Codes
| Code | Description |
|---|---|
| 84 | Decryption Failed - Possible key error or data corruption |
| 83 | Authentication Failed - Signature verification failed or parameter error |
Error Response Format
{
"code": 83,
"message": "Signature verification failed",
"logUUID": "6589bf8d-fe74-48bd-841a-71bf8f848f86"
}
Security Recommendations
- Protect Secret Key: Never store Secret Key in Operator code or public locations
- Use HTTPS: All API requests must be transmitted via HTTPS
- Timestamp verification: Ensure timestamp is within a reasonable range (recommended ±1 minute)
- Nonce uniqueness: Use a unique nonce for each request to prevent replay attacks
- Token Management: Refresh accessToken regularly, do not use the same token for extended periods
- Error handling: Properly handle Authentication errors, avoid exposing sensitive information
Next Steps
Learn how to Get Access Token to start using the API.