Trackops signs all webhooks so you can verify they are genuinely from us and have not been tampered with.
Why Signature Verification Matters
Signature verification protects you from:
- Spoofed requests pretending to be from Trackops
- Tampered payload data
- Replay attacks (someone resending old webhooks)
Headers We Send
Every webhook includes these three additional headers:
| Header | Description |
| X-Trackops-Signature | HMAC-SHA256 signature of the request |
| X-Trackops-Timestamp | Unix timestamp (seconds) when the webhook was sent |
| X-Trackops-Token | Unique random token for this webhook |
How to Verify the Webhook
Step 1: Obtain your Signing Key
When you create a webhook in your API token settings, the system will generate a new webhook signing key. Signing keys are unique per webhook. Locate your API webhook and securely obtain the webhook signing key. Webhook signing keys should be treated like passwords and stored accordingly.
Step 2: Verify the Signature using HMAC
HMAC (Hash-based Message Authentication Code) is a secure way to verify that a webhook really came from Trackops and that the data has not been altered. This process guarantees:
- The request came from Trackops (only we know the signing key)
- The payload wasn't changed in transit
- Combined with the timestamp and token, it also helps prevent replay attacks
Use functions in your desired programming language to generate an SHA256 HMAC signature and compare the generated output to the Trackops signature header. If the signature matches exactly, the webhook is valid and can be trusted.
Node.js Example
const crypto = require('crypto');
const verify = (rawBody, headers, signingKey) => {
const sig = headers['x-trackops-signature'];
const ts = headers['x-trackops-timestamp'];
const token = headers['x-trackops-token'];
const data = ts + ':' + token + ':' + rawBody;
const expected = crypto.createHmac('sha256', signingKey)
.update(data)
.digest('hex');
return expected === sig;
};
PHP Example
function verifyWebhook($rawBody, $headers, $signingKey) {
$sig = $headers['X-Trackops-Signature'] ?? '';
$ts = $headers['X-Trackops-Timestamp'] ?? '';
$token = $headers['X-Trackops-Token'] ?? '';
$data = $ts . ':' . $token . ':' . $rawBody;
$expected = hash_hmac('sha256', $data, $signingKey);
return hash_equals($expected, $sig);
}
Python Example
import hmac
import hashlib
def verify_webhook(raw_body, headers, signing_key):
sig = headers.get('X-Trackops-Signature')
ts = headers.get('X-Trackops-Timestamp')
token = headers.get('X-Trackops-Token')
data = f"{ts}:{token}:{raw_body.decode('utf-8')}"
expected = hmac.new(
key=signing_key.encode(),
msg=data.encode(),
digestmod=hashlib.sha256
).hexdigest()
return hmac.compare_digest(expected, sig)