The Opterius Agent exposes an HTTP API on 127.0.0.1:7443. The Panel uses this API internally to perform server operations. If you are building custom tooling or automation that talks directly to the Agent — bypassing the Panel — you need to sign every request using HMAC-SHA256.
This is an advanced topic. Most integrations should use the Panel API instead.
Why HMAC, Not Bearer Tokens
The Agent API is intentionally low-level and stateless. Bearer tokens require a token store; HMAC requires only a shared secret. Because the Agent is a compiled binary running on the server, a shared secret in /etc/opterius/agent.conf is the simplest robust option.
The Secret Key
The secret is stored in /etc/opterius/agent.conf:
cat /etc/opterius/agent.conf
Look for the secret_key field. The Panel reads the same value from its database record for the server. The two must match — if they diverge (e.g. after manual edits), the Panel will receive 401 errors from the Agent and show it as offline.
Signature Formula
HMAC-SHA256(secret, timestamp + method + path + body)
Where:
- secret — the raw value of
secret_keyfromagent.conf, UTF-8 encoded - timestamp — current time in RFC 3339 format, e.g.
2026-04-08T14:32:00Z - method — HTTP method in uppercase:
GET,POST,DELETE,PUT - path — the full request path including leading slash, e.g.
/account/create - body — the raw JSON request body as a string; empty string
""for requests with no body
The components are concatenated directly with no separator.
String to sign example (POST /account/create):
2026-04-08T14:32:00ZPOST/account/create{"username":"alice","domain":"alice.example.com"}
The resulting HMAC is hex-encoded (lowercase).
Request Headers
Every request to the Agent must include:
| Header | Value |
|---|---|
X-Signature |
Hex-encoded HMAC-SHA256 signature |
X-Timestamp |
RFC 3339 timestamp used in the signature |
Content-Type |
application/json (for POST/PUT requests) |
The Agent rejects requests where the timestamp differs from server time by more than 5 minutes. This prevents replay attacks. Ensure your system clock is accurate (NTP sync recommended).
Python Example
import hmac
import hashlib
import json
import time
from datetime import datetime, timezone
import requests
SECRET_KEY = "your-secret-key-here" # from /etc/opterius/agent.conf
AGENT_URL = "http://127.0.0.1:7443"
def sign_request(method: str, path: str, body: str = "") -> dict:
"""Return the headers needed to authenticate an Agent API request."""
timestamp = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
message = timestamp + method.upper() + path + body
signature = hmac.new(
SECRET_KEY.encode("utf-8"),
message.encode("utf-8"),
hashlib.sha256,
).hexdigest()
return {
"X-Signature": signature,
"X-Timestamp": timestamp,
"Content-Type": "application/json",
}
# Example: create an account
payload = {
"username": "alice",
"domain": "alice.example.com",
"email": "alice@example.com",
"password": "s3cur3p@ss",
"package_id": 1,
}
body = json.dumps(payload)
headers = sign_request("POST", "/account/create", body)
response = requests.post(f"{AGENT_URL}/account/create", headers=headers, data=body)
print(response.status_code, response.json())
[!NOTE]
hmac.newis used here for Python's standard library. If you are using Python 3.7+,hmac.newis equivalent tohmac.HMAC. The standard libraryhmacmodule is always preferred over third-party alternatives for correctness.
Error Responses
| Status | Meaning |
|---|---|
| 401 | Signature invalid or timestamp out of range |
| 403 | Valid signature but license check failed — see License Invalid |
A 401 response means either the secret doesn't match, the timestamp is stale, or the string-to-sign was assembled incorrectly. Double-check the concatenation order: timestamp → method → path → body.