TrustPortDocs

Add an endpoint

In the dashboardWebhooks›Add endpoint
  1. 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.

  2. Save the signing secret

    It is shown once. You need it to check that requests really come from TrustPort.

  3. Send a test

    Send test delivers a webhook.test event straight away and shows whether your server accepted it.

Events

EventSent when
UserCreatedA user is created
UserUpdatedA user’s profile or status changes
UserDeletedA user is deleted
LoginSuccessSomeone signs in
LoginFailureA sign-in fails
LoginBlockedRadar or an action refuses a sign-in
RoleAssignedA role is given to a user
RoleRevokedA role is taken away
AccountLockedAn account is locked
RiskScoreHighRadar gives a sign-in a high score
ReviewCreatedAn access review starts
DecisionMadeAn access request or review item is decided
ProvisioningCompletedAccess was granted or removed after a decision
ProvisioningFailedGranting or removing access failed

What you receive

Request body
{
  "id": "evt_01J…",
  "type": "UserCreated",
  "created_at": "2026-10-10T19:20:11Z",
  "tenant_id": "…",
  "actor_id": "…",
  "data": { … }
}
HeaderValue
X-TrustPort-EventThe event type
X-TrustPort-Event-IdThe event ID. Use it to ignore duplicates
X-TrustPort-DeliveryThis delivery’s ID
X-TrustPort-Signaturet=<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
}
Verify against the raw body bytes. Parsing the JSON and serialising it again changes the bytes and the signature won't match.

Retries and failures

If your endpoint doesn't answer with a 2xx, TrustPort tries again on this schedule:

AttemptAfter
2nd10 seconds
3rd1 minute
4th5 minutes
5th30 minutes
6th and last2 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.

© TrustPort IdentitySomething unclear? Tell us and we'll fix the page.