1. Overview
This document provides a detailed explanation of how to generate a Client Access Token for authenticating Annex Cloud public API calls.
The token is a JSON Web Token (JWT) signed using the HMAC-SHA256 algorithm to ensure:
- Data integrity – the request cannot be altered without detection.
- Authentication – confirming the request comes from a trusted client.
This guide covers:
- JWT structure and components
- How to generate the HMAC value for both POST/PATCH and GET requests
- Step-by-step Python implementation example
- Required HTTP headers when calling Annex Cloud APIs
Library used - jwt·PyPI2. Understanding JWT
A JWT consists of three parts, each Base64URL-encoded and separated by a period (.):
<base64url-encoded header>.<base64url-encoded payload>.<base64url-encoded signature>
2.1. JWT Components
a. Header
Defines the type of token and the signing algorithm used.
{
"alg": "HS256",
"typ": "JWT"
} - alg: Signing algorithm (HS256 = HMAC with SHA-256)
- typ: Token type (JWT)
b. Payload
Contains claims and authentication-related data.
Mandatory claims:
- sub – Client identifier (shared during integration)
- exp – Expiration time (in Unix timestamp seconds; ensures the token is valid only for a set duration)
- site_id – Your Annex Cloud site ID
-
hmac – Base64-encoded HMAC-SHA256 signature of either:
- The request JSON payload (POST/PATCH requests), or
- The query parameter value (GET requests)
Example Payload:
{
"sub": "socialannextestsite",
"exp": 1568674228,
"site_id": "yoursiteid",
"hmac": "generated_hmac_here"
}
c. Signature
The JWT signature is created as follows:
HMACSHA256( base64url(header) + "." + base64url(payload), shared_secret )
Where:
- base64url(header) - Base64URL-encoded JSON header
- base64url(payload) - Base64URL-encoded JSON payload
- shared_secret - Your Annex Cloud shared secret key
3. HMAC Generation Rules
For POST / PATCH Requests
- Take the exact JSON payload you will send in the API request.
- Base64-encode the payload (standard Base64, not Base64URL).
- Generate the HMAC using SHA-256 with your shared secret key.
- Base64-encode the HMAC output.
- Insert this Base64-encoded HMAC into the hmac field in the JWT payload.
For GET Requests
- Take the query parameter value you will send.
- Convert it to JSON format (enclose it in quotes).
- Base64-encode this JSON string.
- Generate the HMAC using SHA-256 with your shared secret key.
- Base64-encode the HMAC output.
- Insert this Base64-encoded HMAC into the hmac field in the JWT payload.
Important: The payload or parameter used to generate the HMAC must exactly match what is sent in the API request. Even a single space difference will cause authentication failure.
4. Python Implementation Example
import json
import base64
import hmac
import hashlib
import jwt
import time
def generate_jwt_token(payload_json, key, site_id, site_name):
"""
Generates a JWT token and HMAC from the given payload.
:param payload_json: Dictionary containing payload data
:param key: Secret key for HMAC and JWT signing
:param site_id: Site ID to include in the JWT payload
:param site_name: Site name to include in the JWT payload
:return: JWT token as a string
"""
# Convert the payload to a compact JSON string
compact_json = json.dumps(payload_json, separators=(",", ":"))
# Base64 encode the payload
payload_base64 = base64.b64encode(compact_json.encode()).decode()
# Generate HMAC
hmac_value = base64.b64encode(
hmac.new(key.encode(), payload_base64.encode(), hashlib.sha256).digest()
).decode()
# Generate the JWT token
token_data = {
"sub": site_name,
"exp": int(time.time()) + 86400000, # Expiration time (10 days from now)
"site_id": site_id,
"hmac": hmac_value
}
jwt_token = jwt.encode(token_data, key, algorithm="HS256")
return jwt_token5. Required HTTP Headers for API Calls
When sending requests to Annex Cloud APIs, you must include the following headers:
Header Name |
Value |
Description |
|---|---|---|
Authorization |
Bearer <JWT_access_token> |
The JWT generated using the above process |
X-AnnexCloud-Site |
<site_id> |
Your Annex Cloud site ID |
Content-Type |
application/json |
Request body format |
POST /api/3.0/points HTTP/1.1
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
X-AnnexCloud-Site: yoursiteid
Content-Type: application/json