Webhooks
Get notified in your own systems when things happen in AssetTrove, and verify that each message is genuine.
A webhook sends a message to your system whenever something happens in AssetTrove. For example: open a service desk ticket when a compliance control fails, or update your ERP when a depreciation period closes. You need permission to manage webhooks (Owners and Admins have it).
Add an endpoint
- Go to Webhooks and add an endpoint. It must be a public HTTPS address.
- Choose the events you want.
- Copy the signing secret.
- Select Send test to receive a
ping.
Events
| Event | When |
|---|---|
asset.created, asset.updated |
An asset is added or changed |
asset.assigned, asset.returned, asset.transferred |
Custody changes |
asset.retired, asset.disposed, asset.lost, asset.found |
Lifecycle changes |
asset.recovery_requested |
A device needs collecting from someone who left |
discovery.run_completed |
A discovery run finished |
device.match_conflict |
A device needs review |
allocation.created, allocation.revoked, allocation.promoted |
Licence seats change |
entitlement.expiring |
90, 60, 30 and 7 days before an entitlement ends |
contract.renewal_notice |
A contract's renewal notice deadline is near |
reconciliation.completed |
A licence position run finished |
compliance.shortfall_detected |
A product is short of licences |
reclamation.candidate_detected, reclamation.reclaimed, reclamation.failed |
Reclamation progress |
user.provisioned, user.deactivated, user.reactivated |
People change |
depreciation.period_closed |
A month is closed, with totals per book and cost centre |
compliance.control_failed |
A compliance check failed |
Messages contain IDs and a small summary, never secrets. Fetch more detail with the API if you need it.
Verify every message
Each message has an ITAM-Signature header: t=<unix time>,v1=<signature>. The signature is an HMAC-SHA256 of the time, a full stop, and the raw body, using your signing secret. Reject messages older than 5 minutes, and compare signatures in constant time.
import crypto from "node:crypto";
function isGenuine(rawBody, header, secret) {
const parts = Object.fromEntries(header.split(",").map(p => p.split("=")));
const age = Math.abs(Date.now() / 1000 - Number(parts.t));
if (!parts.t || age > 300) return false;
const expected = crypto.createHmac("sha256", secret).update(parts.t + "." + rawBody).digest("hex");
// During secret rotation the header holds two v1 values; accept either.
return header.split(",").filter(p => p.startsWith("v1=")).some(p => {
const got = Buffer.from(p.slice(3), "hex"), want = Buffer.from(expected, "hex");
return got.length === want.length && crypto.timingSafeEqual(got, want);
});
}
Delivery and retries
- Any 2xx response counts as delivered.
- Failed deliveries are retried after 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours and 24 hours.
- After 3 days of continuous failure, the endpoint is disabled and admins are emailed.
- You can see every delivery and redeliver any of them from the endpoint's page.
- Messages can occasionally arrive more than once. Use the
ITAM-Event-Idheader to ignore duplicates.
Rotating the secret
Select Rotate secret. The old secret keeps working for 24 hours, and during that time each message carries both signatures, so you can switch over without missing anything.