Webhooks
Webhooks tell your systems about sign-ins and account changes as they happen. TrustPort sends a signed JSON POST to your endpoint and retries if it doesn’t get through.
Add an endpoint
- Enter your URL and pick events
Use an https URL on your server, such as
https://api.example.com/webhooks/trustport. Choose the events you want, or all of them. - Save the signing secret
It is shown once. You need it to check that requests really come from TrustPort.
- Send a test
Send test delivers a
webhook.testevent straight away and shows whether your server accepted it.
Events
| Event | Sent when |
|---|---|
UserCreated | A user is created |
UserUpdated | A user’s profile or status changes |
UserDeleted | A user is deleted |
LoginSuccess | Someone signs in |
LoginFailure | A sign-in fails |
LoginBlocked | Radar or an action refuses a sign-in |
RoleAssigned | A role is given to a user |
RoleRevoked | A role is taken away |
AccountLocked | An account is locked |
RiskScoreHigh | Radar gives a sign-in a high score |
ReviewCreated | An access review starts |
DecisionMade | An access request or review item is decided |
ProvisioningCompleted | Access was granted or removed after a decision |
ProvisioningFailed | Granting or removing access failed |
What you receive
{
"id": "evt_01J…",
"type": "UserCreated",
"created_at": "2026-10-10T19:20:11Z",
"tenant_id": "…",
"actor_id": "…",
"data": { … }
}| Header | Value |
|---|---|
X-TrustPort-Event | The event type |
X-TrustPort-Event-Id | The event ID. Use it to ignore duplicates |
X-TrustPort-Delivery | This delivery’s ID |
X-TrustPort-Signature | t=<timestamp>,v1=<signature> |
actor_id is whoever caused the event, when there is one. Reply with any 2xx status within 10 seconds, and do slow work after you respond. Endpoints must be reachable on the public internet; private and local addresses are refused.
Verify the signature
The signature is an HMAC-SHA256 of <timestamp>.<raw body> using your signing secret, in hex. Recompute it, compare in constant time, and reject requests older than five minutes.
import crypto from 'node:crypto'
// Use the raw request body, exactly as received.
export function verify(rawBody, header, secret) {
const parts = Object.fromEntries(header.split(',').map((p) => p.split('=')))
const expected = crypto
.createHmac('sha256', secret)
.update(`${parts.t}.${rawBody}`)
.digest('hex')
const fresh = Math.abs(Date.now() / 1000 - Number(parts.t)) < 300
const valid = crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(parts.v1))
return fresh && valid
}Retries and failures
If your endpoint doesn't answer with a 2xx, TrustPort tries again on this schedule:
| Attempt | After |
|---|---|
| 2nd | 10 seconds |
| 3rd | 1 minute |
| 4th | 5 minutes |
| 5th | 30 minutes |
| 6th and last | 2 hours |
Because of retries, the same event can arrive more than once. Use X-TrustPort-Event-Id to process each event once.
Check deliveries
Deliveries on an endpoint lists recent attempts with the event, status and number of tries. Redeliver sends one again, for example after you fix a bug. The endpoint list shows the last successful delivery, and marks an endpoint failing with a count of failures in a row.
Rotate the secret or pause an endpoint
Rotate secret issues a new signing secret and the old one stops working, so update your server straight after. Disable an endpoint to pause deliveries without deleting it, and enable it again when you're ready.