Skip to main content

Identity Webhooks

Webhooks enable your applications to receive real-time notifications when events occur in your identity and access management systems. This eliminates the need for polling and ensures your systems stay synchronized with user provisioning, authentication, and access control changes across all integrated platforms.

Unizo normalizes webhook events from Okta, Auth0, Azure AD, OneLogin, and other identity providers into a consistent format. This means you write your webhook handler once and it works with all supported platforms.

Webhook Configuration

To set up webhooks for your integration, visit the Unizo Console Webhooks section for step-by-step configuration guide.

Supported Event Types

These are the event types currently supported by Unizo's Identity webhooks. The list keeps growing as we add support for more events across different platforms.

Event TypeDescriptionTrigger Conditions
user:createdA new user has been createdUser account creation via UI, API, or sync
user:updatedUser profile information has been modifiedProfile updates, attribute changes, or status updates
user:deletedA user account has been deletedUser deletion or deactivation
group:createdA new group has been createdGroup creation via UI or API
group:updatedGroup information has been modifiedGroup name, description, or membership changes
group:deletedA group has been deletedGroup removal from the system
authentication:successSuccessful authentication attemptUser successfully logs in
authentication:failedFailed authentication attemptInvalid credentials or blocked access
role:assignedRole assigned to a userRole assignment via UI or API
role:revokedRole removed from a userRole revocation via UI or API

Webhook Security

All webhooks from Unizo include security headers to verify authenticity:

Headers

HeaderDescription
x-unizo-event-typeThe type of event that triggered the webhook
x-unizo-signatureHMAC SHA-256 signature for request validation
x-unizo-timestampUnix timestamp when the event was sent
x-unizo-delivery-idUnique identifier for this webhook delivery

Signature Verification

Verify the authenticity of incoming webhooks using HMAC SHA-256:

const crypto = require('crypto');

function verifyWebhookSignature(payload, signature, secret) {
  const expectedSignature = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');
  
  return crypto.timingSafeEqual(
    Buffer.from(signature, 'hex'),
    Buffer.from(expectedSignature, 'hex')
  );
}

Event Details

User Events

Event TypeDescriptionTrigger Conditions
user:createdA new user has been createdUser account creation via UI, API, or sync
user:updatedUser profile information has been modifiedProfile updates, attribute changes, or status updates
user:deletedA user account has been deletedUser deletion or deactivation

User Created

user:created

Triggered when a new user account is created in the identity system
POSThttps://api.yourapp.com/webhooks/unizo/identity
Best Practice: Use a dedicated webhook endpoint that can handle multiple event types. You have two architectural options:
• Single endpoint: https://api.yourapp.com/webhooks/unizo - Route all events to one handler
• Category-based endpoints: https://api.yourapp.com/webhooks/unizo/identity - Route by category (identity, ticketing, etc.) for microservices architecture
Headers
NameTypeRequiredDescription
Content-TypestringYesAlways application/json
x-unizo-event-typestringYesEvent type: user:created
x-unizo-webhook-idstringYesUnique webhook configuration ID
x-unizo-delivery-idstringYesUnique delivery ID for idempotency
x-unizo-signaturestringYesHMAC SHA-256 signature
Request Body Schema
PropertyTypeRequiredDescription
typestringYesEvent type identifier
versionstringYesWebhook payload version
user.idstringYesUnique user identifier
user.emailstringYesUser's email address
user.usernamestringNoUser's username
user.firstNamestringYesUser's first name
user.lastNamestringYesUser's last name
user.statusstringYesUser status: active, pending, suspended
user.createdDateTimestringYesISO 8601 timestamp
user.createdByobjectNoUser who created this account
integrationobjectYesIntegration details
Example Payload
{
"type": "user:created",
"version": "1.0.0",
"user": {
"id": "user-123456",
"email": "john.doe@example.com",
"username": "john.doe",
"firstName": "John",
"lastName": "Doe",
"status": "active",
"createdDateTime": "2024-01-15T14:00:00Z",
"createdBy": {
"id": "admin-789",
"email": "admin@example.com"
}
},
"integration": {
"type": "IDENTITY",
"id": "int_123456",
"name": "Okta Production",
"provider": "okta"
}
}
Response
200 OKWebhook processed successfully
400 Bad RequestInvalid webhook payload
401 UnauthorizedInvalid or missing signature

User Updated

user:updated

Triggered when user profile information is modified
POSThttps://api.yourapp.com/webhooks/unizo/scm
Best Practice: Use a dedicated webhook endpoint that can handle multiple event types. You have two architectural options:
• Single endpoint: https://api.yourapp.com/webhooks/unizo - Route all events to one handler
• Category-based endpoints: https://api.yourapp.com/webhooks/unizo/scm - Route by category (scm, ticketing, etc.) for microservices architecture
Headers
NameTypeRequiredDescription
Content-TypestringYesAlways application/json
x-unizo-event-typestringYesEvent type: user:updated
x-unizo-webhook-idstringYesUnique webhook configuration ID
x-unizo-delivery-idstringYesUnique delivery ID for idempotency
x-unizo-signaturestringYesHMAC SHA-256 signature
Request Body Schema
PropertyTypeRequiredDescription
typestringYesEvent type identifier
versionstringYesWebhook payload version
user.idstringYesUnique user identifier
user.emailstringYesUser's email address
user.changesobjectYesObject containing changed fields
user.updatedDateTimestringYesISO 8601 timestamp
user.updatedByobjectNoUser who made the update
integrationobjectYesIntegration details
Example Payload
{
"type": "user:updated",
"version": "1.0.0",
"user": {
"id": "user-123456",
"email": "john.doe@example.com",
"changes": {
"lastName": {
"from": "Doe",
"to": "Smith"
},
"department": {
"from": "Engineering",
"to": "Product"
}
},
"updatedDateTime": "2024-01-15T15:00:00Z",
"updatedBy": {
"id": "admin-789",
"email": "admin@example.com"
}
},
"integration": {
"type": "IDENTITY",
"id": "int_123456",
"name": "Okta Production",
"provider": "okta"
}
}
Response
200 OKWebhook processed successfully
400 Bad RequestInvalid webhook payload
401 UnauthorizedInvalid or missing signature

User Deleted

user:deleted

Triggered when a user account is deleted or deactivated
POSThttps://api.yourapp.com/webhooks/unizo/scm
Best Practice: Use a dedicated webhook endpoint that can handle multiple event types. You have two architectural options:
• Single endpoint: https://api.yourapp.com/webhooks/unizo - Route all events to one handler
• Category-based endpoints: https://api.yourapp.com/webhooks/unizo/scm - Route by category (scm, ticketing, etc.) for microservices architecture
Headers
NameTypeRequiredDescription
Content-TypestringYesAlways application/json
x-unizo-event-typestringYesEvent type: user:deleted
x-unizo-webhook-idstringYesUnique webhook configuration ID
x-unizo-delivery-idstringYesUnique delivery ID for idempotency
x-unizo-signaturestringYesHMAC SHA-256 signature
Request Body Schema
PropertyTypeRequiredDescription
typestringYesEvent type identifier
versionstringYesWebhook payload version
user.idstringYesUnique user identifier
user.emailstringYesUser's email address
user.deletedDateTimestringYesISO 8601 timestamp
user.deletedByobjectNoUser who deleted this account
integrationobjectYesIntegration details
Example Payload
{
"type": "user:deleted",
"version": "1.0.0",
"user": {
"id": "user-123456",
"email": "john.doe@example.com",
"deletedDateTime": "2024-01-15T16:00:00Z",
"deletedBy": {
"id": "admin-789",
"email": "admin@example.com"
}
},
"integration": {
"type": "IDENTITY",
"id": "int_123456",
"name": "Okta Production",
"provider": "okta"
}
}
Response
200 OKWebhook processed successfully
400 Bad RequestInvalid webhook payload
401 UnauthorizedInvalid or missing signature

Group Events

Event TypeDescriptionTrigger Conditions
group:createdA new group has been createdGroup creation via UI or API
group:updatedGroup information has been modifiedGroup name, description, or membership changes
group:deletedA group has been deletedGroup removal from the system

Group Created

group:created

Triggered when a new group is created in the identity system
POSThttps://api.yourapp.com/webhooks/unizo/scm
Best Practice: Use a dedicated webhook endpoint that can handle multiple event types. You have two architectural options:
• Single endpoint: https://api.yourapp.com/webhooks/unizo - Route all events to one handler
• Category-based endpoints: https://api.yourapp.com/webhooks/unizo/scm - Route by category (scm, ticketing, etc.) for microservices architecture
Headers
NameTypeRequiredDescription
Content-TypestringYesAlways application/json
x-unizo-event-typestringYesEvent type: group:created
x-unizo-webhook-idstringYesUnique webhook configuration ID
x-unizo-delivery-idstringYesUnique delivery ID for idempotency
x-unizo-signaturestringYesHMAC SHA-256 signature
Request Body Schema
PropertyTypeRequiredDescription
typestringYesEvent type identifier
versionstringYesWebhook payload version
group.idstringYesUnique group identifier
group.namestringYesGroup name
group.descriptionstringNoGroup description
group.typestringYesGroup type: security, distribution
group.createdDateTimestringYesISO 8601 timestamp
integrationobjectYesIntegration details
Example Payload
{
"type": "group:created",
"version": "1.0.0",
"group": {
"id": "group-789",
"name": "Engineering Team",
"description": "All engineering department members",
"type": "security",
"createdDateTime": "2024-01-15T14:00:00Z"
},
"integration": {
"type": "IDENTITY",
"id": "int_123456",
"name": "Azure AD Production",
"provider": "azure_ad"
}
}
Response
200 OKWebhook processed successfully
400 Bad RequestInvalid webhook payload
401 UnauthorizedInvalid or missing signature

Authentication Events

Event TypeDescriptionTrigger Conditions
authentication:successSuccessful authentication attemptUser successfully logs in
authentication:failedFailed authentication attemptInvalid credentials or blocked access

Authentication Success

authentication:success

Triggered when a user successfully authenticates
POSThttps://api.yourapp.com/webhooks/unizo/scm
Best Practice: Use a dedicated webhook endpoint that can handle multiple event types. You have two architectural options:
• Single endpoint: https://api.yourapp.com/webhooks/unizo - Route all events to one handler
• Category-based endpoints: https://api.yourapp.com/webhooks/unizo/scm - Route by category (scm, ticketing, etc.) for microservices architecture
Headers
NameTypeRequiredDescription
Content-TypestringYesAlways application/json
x-unizo-event-typestringYesEvent type: authentication:success
x-unizo-webhook-idstringYesUnique webhook configuration ID
x-unizo-delivery-idstringYesUnique delivery ID for idempotency
x-unizo-signaturestringYesHMAC SHA-256 signature
Request Body Schema
PropertyTypeRequiredDescription
typestringYesEvent type identifier
versionstringYesWebhook payload version
user.idstringYesUser identifier
user.emailstringYesUser's email address
authentication.methodstringYesAuthentication method used
authentication.ipAddressstringYesClient IP address
authentication.userAgentstringNoClient user agent
authentication.timestampstringYesISO 8601 timestamp
integrationobjectYesIntegration details
Example Payload
{
"type": "authentication:success",
"version": "1.0.0",
"user": {
"id": "user-123456",
"email": "john.doe@example.com"
},
"authentication": {
"method": "password",
"ipAddress": "192.168.1.100",
"userAgent": "Mozilla/5.0...",
"timestamp": "2024-01-15T14:00:00Z"
},
"integration": {
"type": "IDENTITY",
"id": "int_123456",
"name": "Auth0 Production",
"provider": "auth0"
}
}
Response
200 OKWebhook processed successfully
400 Bad RequestInvalid webhook payload
401 UnauthorizedInvalid or missing signature

Role Events

Event TypeDescriptionTrigger Conditions
role:assignedRole assigned to a userRole assignment via UI or API
role:revokedRole removed from a userRole revocation via UI or API

Role Assigned

role:assigned

Triggered when a role is assigned to a user
POSThttps://api.yourapp.com/webhooks/unizo/scm
Best Practice: Use a dedicated webhook endpoint that can handle multiple event types. You have two architectural options:
• Single endpoint: https://api.yourapp.com/webhooks/unizo - Route all events to one handler
• Category-based endpoints: https://api.yourapp.com/webhooks/unizo/scm - Route by category (scm, ticketing, etc.) for microservices architecture
Headers
NameTypeRequiredDescription
Content-TypestringYesAlways application/json
x-unizo-event-typestringYesEvent type: role:assigned
x-unizo-webhook-idstringYesUnique webhook configuration ID
x-unizo-delivery-idstringYesUnique delivery ID for idempotency
x-unizo-signaturestringYesHMAC SHA-256 signature
Request Body Schema
PropertyTypeRequiredDescription
typestringYesEvent type identifier
versionstringYesWebhook payload version
user.idstringYesUser identifier
user.emailstringYesUser's email address
role.idstringYesRole identifier
role.namestringYesRole name
role.permissionsarrayNoList of permissions
assignedDateTimestringYesISO 8601 timestamp
assignedByobjectNoUser who assigned the role
integrationobjectYesIntegration details
Example Payload
{
"type": "role:assigned",
"version": "1.0.0",
"user": {
"id": "user-123456",
"email": "john.doe@example.com"
},
"role": {
"id": "role-456",
"name": "Admin",
"permissions": [
"read",
"write",
"delete"
]
},
"assignedDateTime": "2024-01-15T14:00:00Z",
"assignedBy": {
"id": "admin-789",
"email": "admin@example.com"
},
"integration": {
"type": "IDENTITY",
"id": "int_123456",
"name": "Okta Production",
"provider": "okta"
}
}
Response
200 OKWebhook processed successfully
400 Bad RequestInvalid webhook payload
401 UnauthorizedInvalid or missing signature

Webhook Delivery & Retries

Unizo implements automatic retry logic for failed webhook deliveries:

  1. Initial Delivery: Immediate
  2. First Retry: After 1 minute
  3. Second Retry: After 5 minutes
  4. Third Retry: After 15 minutes
  5. Final Retry: After 1 hour

Webhooks are considered failed if:

  • Your endpoint returns a non-2xx status code
  • Connection timeout (30 seconds)
  • SSL/TLS errors

Best Practices

1. Idempotency

Idempotent Webhook Handler

async function handleWebhook(request) {
const deliveryId = request.headers['x-unizo-delivery-id'];

// Check if already processed
if (await isProcessed(deliveryId)) {
  return { status: 200, message: 'Already processed' };
}

// Process webhook
await processWebhook(request.body);

// Mark as processed
await markProcessed(deliveryId);

return { status: 200 };
}

2. Async Processing

Asynchronous Processing

app.post('/webhooks/identity', (req, res) => {
// Validate signature
if (!verifySignature(req)) {
  return res.status(401).send('Invalid signature');
}

// Queue for processing
identityQueue.add(req.body);

// Return immediately
res.status(200).send('OK');
});

3. Error Handling

Comprehensive Error Handling

async function processWebhook(payload) {
try {
  switch (payload.type) {
    case 'user:created':
      await handleUserCreated(payload);
      break;
    case 'role:assigned':
      await handleRoleAssigned(payload);
      break;
    default:
      logger.warn(`Unknown webhook type: ${payload.type}`);
  }
} catch (error) {
  logger.error('Webhook processing failed', {
    error: error.message,
    payload,
    stack: error.stack
  });
  throw error;
}
}

Need Help?

For webhook-related support: