Signature Guide — HMAC-SHA256
The Base API, Report API, and Seamless Wallet Callback all use the same HMAC-SHA256 algorithm.
They differ in which side creates the signature and which side verifies it, and in how the signature data is ordered: the Base API and Report API sort field names alphabetically, while the Seamless Wallet Callback uses the fixed order documented for each endpoint.
Algorithm#
dataStr = "{publicKey}:{timestamp}:{field1Value}:{field2Value}:..."
signature = hex(HMAC-SHA256(privateKey, dataStr))
Body fields are sorted alphabetically by field name before concatenation
Signature is a hex-encoded string (lowercase)
Timestamp is a Unix timestamp (seconds)
1. Base API & Report API#
Agent Creates Signature, Sends to Hectic Play
The agent creates the signature and sends it along with the request.| Header | Value |
|---|
X-PUBLIC-KEY | Agent's public key |
X-TIMESTAMP | Unix timestamp (seconds) |
X-SIGNATURE | hex(HMAC-SHA256 signature) |
Example: POST /capi/game/create-player#
Signature fields (sorted): currency, playerUsernamedataStr = "{publicKey}:{timestamp}:{currency}:{playerUsername}"
publicKey = "pk_abc123"
privateKey = "sk_secret456"
timestamp = "1710691234"
Body:
{
"playerName": "John Doe",
"playerUsername": "johndoe123",
"currency": "USD"
}
Sorted fields: currency, playerUsername
dataStr = "pk_abc123:1710691234:USD:johndoe123"
signature = hex(HMAC-SHA256("sk_secret456", "pk_abc123:1710691234:USD:johndoe123"))
= "a1b2c3d4..."
How Hectic Play Verifies#
1.
Extract X-PUBLIC-KEY, X-TIMESTAMP, X-SIGNATURE from headers
2.
Validate timestamp is within ±10 seconds of server time
3.
Look up the private key from the database using the public key
4.
Parse the body and sort field names alphabetically
5.
Construct dataStr: {publicKey}:{timestamp}:{sorted_values...}
6.
Compute HMAC-SHA256 and compare with X-SIGNATURE
2. Seamless Wallet Callback#
Agent Verifies Signature from Hectic Play
Hectic Play creates the signature and sends it along with the callback request.| Header | Value |
|---|
X-PUBLIC-KEY | Agent's public key |
X-TIMESTAMP | Unix timestamp (seconds) |
X-SIGNATURE | hex(HMAC-SHA256 signature) |
X-Request-ID | UUID v4 (unique per request) |
Example: POST /settlement#
Signature data: {gameCode}:{roundID}:{currency}:{playerUsername}:{bet}:{payout}dataStr = "{publicKey}:{timestamp}:{gameCode}:{roundID}:{currency}:{playerUsername}:{bet}:{payout}"
Headers:
X-PUBLIC-KEY: pk_abc123
X-TIMESTAMP: 1710691234
X-SIGNATURE: m3n4o5p6...
X-Request-ID: 7c9e6679-7425-40de-944b-e07fc1f90ae7
Body:
{
"gameCode": "MJW",
"roundID": "550e8400-e29b-41d4-a716-446655440000",
"playerUsername": "johndoe123",
"currency": "USD",
"bet": 10,
"payout": 25.5
}
dataStr = "pk_abc123:1710691234:MJW:550e8400-e29b-41d4-a716-446655440000:USD:johndoe123:10:25.5"
verify: hex(HMAC-SHA256("sk_secret456", dataStr)) == "m3n4o5p6..."
How the Agent Should Verify#
1.
Extract X-PUBLIC-KEY, X-TIMESTAMP, X-SIGNATURE from headers
2.
Validate that the timestamp is not too old (recommended: ±60 seconds)
3.
Look up the private key that matches the public key
4.
Construct dataStr according to the endpoint format
5.
Compute hex(HMAC-SHA256(privateKey, dataStr))
6.
Compare with X-SIGNATURE — if they match, the request is authentic
Code Examples#
Rust#
Node.js#
Python#
Modified at 2026-09-14 10:16:00