Organization Sync Events¶
Complete reference for all organization-level webhook events with TypeScript types and JSON payload examples.
See also: Organization Sync Overview | Webhooks Guide
Tenant Events¶
Tenant events fire when organizations are created, modified, or removed from AuthVital.
TypeScript Types¶
interface TenantSettings {
allow_signups: boolean; // Whether self-signup is enabled
require_mfa: boolean; // Whether MFA is required for all users
allowed_email_domains: string[]; // Restrict signups to specific domains
session_lifetime_minutes: number; // Session duration
password_policy: 'standard' | 'strict'; // Password requirements
}
interface TenantData {
tenant_id: string; // Unique tenant identifier
name: string; // Display name
slug: string; // URL-safe identifier
plan: 'free' | 'starter' | 'pro' | 'enterprise'; // Subscription plan
settings: TenantSettings; // Tenant configuration
}
interface TenantCreatedData extends TenantData {
created_by_sub: string; // Subject ID of creator
created_at: string; // ISO timestamp
}
interface TenantUpdatedData extends TenantData {
changed_fields: string[]; // Fields that changed
previous_values: Record<string, unknown>; // Previous field values
updated_by_sub: string; // Subject ID of updater
}
interface TenantDeletedData {
tenant_id: string;
name: string;
slug: string;
deleted_by_sub: string;
deleted_at: string;
}
interface TenantSuspendedData extends TenantData {
suspended_by_sub: string;
suspended_at: string;
reason?: string;
}
// Event types
type TenantCreatedEvent = BaseEvent<'tenant.created', TenantCreatedData>;
type TenantUpdatedEvent = BaseEvent<'tenant.updated', TenantUpdatedData>;
type TenantDeletedEvent = BaseEvent<'tenant.deleted', TenantDeletedData>;
type TenantSuspendedEvent = BaseEvent<'tenant.suspended', TenantSuspendedData>;
tenant.created¶
Fires when a new tenant (organization) is provisioned in AuthVital.
{
"id": "evt_01HQTNT001ABC",
"type": "tenant.created",
"timestamp": "2024-01-15T10:00:00.000Z",
"tenant_id": "tnt_acme123",
"application_id": null,
"data": {
"tenant_id": "tnt_acme123",
"name": "Acme Corporation",
"slug": "acme-corp",
"plan": "pro",
"created_by_sub": "usr_founder001",
"created_at": "2024-01-15T10:00:00.000Z",
"settings": {
"allow_signups": true,
"require_mfa": false,
"allowed_email_domains": ["acme.com", "acme.io"],
"session_lifetime_minutes": 480,
"password_policy": "standard"
}
}
}
Handler behavior:
// Handler creates organization record
await prisma.organization.create({
data: {
id: 'tnt_acme123',
name: 'Acme Corporation',
slug: 'acme-corp',
plan: 'pro',
createdBySub: 'usr_founder001',
allowSignups: true,
requireMfa: false,
allowedEmailDomains: ['acme.com', 'acme.io'],
sessionLifetimeMinutes: 480,
passwordPolicy: 'standard',
status: 'active',
syncedAt: new Date(),
},
});
tenant.updated¶
Fires when tenant settings or plan changes. Includes changed_fields and previous_values for audit trails.
{
"id": "evt_01HQTNT002DEF",
"type": "tenant.updated",
"timestamp": "2024-01-20T14:30:00.000Z",
"tenant_id": "tnt_acme123",
"application_id": null,
"data": {
"tenant_id": "tnt_acme123",
"name": "Acme Corporation",
"slug": "acme-corp",
"plan": "enterprise",
"changed_fields": ["plan", "settings.require_mfa"],
"previous_values": {
"plan": "pro",
"settings.require_mfa": false
},
"updated_by_sub": "usr_admin001",
"settings": {
"allow_signups": true,
"require_mfa": true,
"allowed_email_domains": ["acme.com", "acme.io"],
"session_lifetime_minutes": 480,
"password_policy": "strict"
}
}
}
Handler behavior:
// Handler updates changed fields and logs audit entry
await prisma.organization.update({
where: { id: 'tnt_acme123' },
data: {
plan: 'enterprise',
requireMfa: true,
passwordPolicy: 'strict',
syncedAt: new Date(),
},
});
// Optional: Create audit log entry
await prisma.organizationAuditLog.create({
data: {
organizationId: 'tnt_acme123',
eventType: 'tenant.updated',
changedFields: ['plan', 'settings.require_mfa'],
previousValues: { plan: 'pro', 'settings.require_mfa': false },
changedBySub: 'usr_admin001',
},
});
Billing Integration
The tenant.updated event with plan in changed_fields is perfect for syncing subscription changes to Stripe or your billing system. See Billing Use Case.
tenant.deleted¶
Fires when a tenant is permanently removed from AuthVital.
{
"id": "evt_01HQTNT003GHI",
"type": "tenant.deleted",
"timestamp": "2024-02-01T09:00:00.000Z",
"tenant_id": "tnt_oldcorp456",
"application_id": null,
"data": {
"tenant_id": "tnt_oldcorp456",
"name": "Old Corp Inc",
"slug": "old-corp",
"deleted_by_sub": "usr_superadmin001",
"deleted_at": "2024-02-01T09:00:00.000Z"
}
}
Handler behavior:
// Handler deletes organization (cascades to apps and SSO providers)
await prisma.organization.delete({
where: { id: 'tnt_oldcorp456' },
});
Cascade Deletion
When you delete an organization, the Prisma schema cascades the deletion to related Application and SsoProvider records. Ensure this matches your data retention requirements.
tenant.suspended¶
Fires when a tenant is deactivated (soft disable). Users cannot authenticate but data is preserved.
{
"id": "evt_01HQTNT004JKL",
"type": "tenant.suspended",
"timestamp": "2024-01-25T16:00:00.000Z",
"tenant_id": "tnt_suspended789",
"application_id": null,
"data": {
"tenant_id": "tnt_suspended789",
"name": "Suspended Company",
"slug": "suspended-co",
"plan": "starter",
"suspended_by_sub": "usr_superadmin001",
"suspended_at": "2024-01-25T16:00:00.000Z",
"reason": "Payment failed after 3 retry attempts",
"settings": {
"allow_signups": false,
"require_mfa": false,
"allowed_email_domains": [],
"session_lifetime_minutes": 480,
"password_policy": "standard"
}
}
}
Handler behavior:
// Handler sets status to suspended
await prisma.organization.update({
where: { id: 'tnt_suspended789' },
data: {
status: 'suspended',
suspendedAt: new Date('2024-01-25T16:00:00.000Z'),
suspendedBySub: 'usr_superadmin001',
suspendedReason: 'Payment failed after 3 retry attempts',
syncedAt: new Date(),
},
});
Application Events¶
Application events fire when OAuth applications are created, modified, or removed from a tenant.
TypeScript Types¶
interface ApplicationConfig {
redirect_uris: string[]; // Allowed redirect URIs
post_logout_redirect_uris: string[]; // Allowed post-logout URIs
allowed_scopes: string[]; // Permitted OAuth scopes
grant_types: ('authorization_code' | 'refresh_token' | 'client_credentials')[];
token_endpoint_auth_method: 'client_secret_basic' | 'client_secret_post' | 'none';
access_token_ttl_seconds: number; // Access token lifetime
refresh_token_ttl_seconds: number; // Refresh token lifetime
}
interface ApplicationData {
application_id: string; // Unique application ID
tenant_id: string; // Parent tenant ID
name: string; // Display name
description?: string; // Optional description
client_id: string; // OAuth client ID
application_type: 'web' | 'spa' | 'native' | 'machine';
config: ApplicationConfig;
is_active: boolean;
}
interface ApplicationCreatedData extends ApplicationData {
created_by_sub: string;
created_at: string;
}
interface ApplicationUpdatedData extends ApplicationData {
changed_fields: string[];
previous_values: Record<string, unknown>;
updated_by_sub: string;
}
interface ApplicationDeletedData {
application_id: string;
tenant_id: string;
name: string;
client_id: string;
deleted_by_sub: string;
deleted_at: string;
}
// Event types
type ApplicationCreatedEvent = BaseEvent<'application.created', ApplicationCreatedData>;
type ApplicationUpdatedEvent = BaseEvent<'application.updated', ApplicationUpdatedData>;
type ApplicationDeletedEvent = BaseEvent<'application.deleted', ApplicationDeletedData>;
application.created¶
Fires when a new OAuth application is registered to a tenant.
{
"id": "evt_01HQAPP001ABC",
"type": "application.created",
"timestamp": "2024-01-15T11:00:00.000Z",
"tenant_id": "tnt_acme123",
"application_id": "app_dashboard456",
"data": {
"application_id": "app_dashboard456",
"tenant_id": "tnt_acme123",
"name": "Acme Dashboard",
"description": "Main customer dashboard",
"client_id": "acme_dashboard_prod",
"application_type": "spa",
"is_active": true,
"created_by_sub": "usr_admin001",
"created_at": "2024-01-15T11:00:00.000Z",
"config": {
"redirect_uris": [
"https://dashboard.acme.com/callback",
"http://localhost:3000/callback"
],
"post_logout_redirect_uris": [
"https://dashboard.acme.com"
],
"allowed_scopes": ["openid", "profile", "email"],
"grant_types": ["authorization_code", "refresh_token"],
"token_endpoint_auth_method": "none",
"access_token_ttl_seconds": 3600,
"refresh_token_ttl_seconds": 604800
}
}
}
Handler behavior:
// Handler creates application record
await prisma.application.create({
data: {
id: 'app_dashboard456',
organizationId: 'tnt_acme123',
name: 'Acme Dashboard',
description: 'Main customer dashboard',
clientId: 'acme_dashboard_prod',
applicationType: 'spa',
isActive: true,
createdBySub: 'usr_admin001',
redirectUris: [
'https://dashboard.acme.com/callback',
'http://localhost:3000/callback',
],
postLogoutRedirectUris: ['https://dashboard.acme.com'],
allowedScopes: ['openid', 'profile', 'email'],
grantTypes: ['authorization_code', 'refresh_token'],
tokenEndpointAuthMethod: 'none',
accessTokenTtlSeconds: 3600,
refreshTokenTtlSeconds: 604800,
syncedAt: new Date(),
},
});
application.updated¶
Fires when application configuration changes (redirect URIs, scopes, etc.).
{
"id": "evt_01HQAPP002DEF",
"type": "application.updated",
"timestamp": "2024-01-18T15:30:00.000Z",
"tenant_id": "tnt_acme123",
"application_id": "app_dashboard456",
"data": {
"application_id": "app_dashboard456",
"tenant_id": "tnt_acme123",
"name": "Acme Dashboard",
"description": "Main customer dashboard",
"client_id": "acme_dashboard_prod",
"application_type": "spa",
"is_active": true,
"changed_fields": ["config.redirect_uris", "config.allowed_scopes"],
"previous_values": {
"config.redirect_uris": [
"https://dashboard.acme.com/callback",
"http://localhost:3000/callback"
],
"config.allowed_scopes": ["openid", "profile", "email"]
},
"updated_by_sub": "usr_admin001",
"config": {
"redirect_uris": [
"https://dashboard.acme.com/callback",
"https://staging.dashboard.acme.com/callback",
"http://localhost:3000/callback"
],
"post_logout_redirect_uris": [
"https://dashboard.acme.com"
],
"allowed_scopes": ["openid", "profile", "email", "offline_access"],
"grant_types": ["authorization_code", "refresh_token"],
"token_endpoint_auth_method": "none",
"access_token_ttl_seconds": 3600,
"refresh_token_ttl_seconds": 604800
}
}
}
Handler behavior:
// Handler updates changed configuration
await prisma.application.update({
where: { id: 'app_dashboard456' },
data: {
redirectUris: [
'https://dashboard.acme.com/callback',
'https://staging.dashboard.acme.com/callback',
'http://localhost:3000/callback',
],
allowedScopes: ['openid', 'profile', 'email', 'offline_access'],
syncedAt: new Date(),
},
});
application.deleted¶
Fires when an application is removed from a tenant.
{
"id": "evt_01HQAPP003GHI",
"type": "application.deleted",
"timestamp": "2024-02-01T10:00:00.000Z",
"tenant_id": "tnt_acme123",
"application_id": "app_legacy789",
"data": {
"application_id": "app_legacy789",
"tenant_id": "tnt_acme123",
"name": "Legacy App",
"client_id": "acme_legacy_deprecated",
"deleted_by_sub": "usr_admin001",
"deleted_at": "2024-02-01T10:00:00.000Z"
}
}
Handler behavior:
// Handler deletes application record
await prisma.application.delete({
where: { id: 'app_legacy789' },
});
SSO Events¶
SSO events fire when Single Sign-On providers are configured, modified, or removed from a tenant.
TypeScript Types¶
interface SsoProviderConfig {
client_id: string; // OAuth client ID for the provider
issuer?: string; // OIDC issuer URL (for OIDC/SAML)
authorization_endpoint?: string; // OAuth authorization URL
token_endpoint?: string; // OAuth token URL
userinfo_endpoint?: string; // OIDC userinfo URL
domains: string[]; // Email domains that trigger this SSO
attribute_mapping: Record<string, string>; // Map provider claims to AuthVital claims
}
interface SsoProviderData {
provider_id: string; // Unique provider ID
tenant_id: string; // Parent tenant ID
provider_type: 'google' | 'microsoft' | 'okta' | 'saml' | 'oidc';
display_name: string; // Display name for login UI
is_enabled: boolean; // Whether SSO is active
config: SsoProviderConfig;
}
interface SsoProviderAddedData extends SsoProviderData {
created_by_sub: string;
created_at: string;
}
interface SsoProviderUpdatedData extends SsoProviderData {
changed_fields: string[];
previous_values: Record<string, unknown>;
updated_by_sub: string;
}
interface SsoProviderRemovedData {
provider_id: string;
tenant_id: string;
provider_type: string;
display_name: string;
removed_by_sub: string;
removed_at: string;
}
// Event types
type SsoProviderAddedEvent = BaseEvent<'sso.provider_added', SsoProviderAddedData>;
type SsoProviderUpdatedEvent = BaseEvent<'sso.provider_updated', SsoProviderUpdatedData>;
type SsoProviderRemovedEvent = BaseEvent<'sso.provider_removed', SsoProviderRemovedData>;
sso.provider_added¶
Fires when an SSO provider is configured for a tenant.
{
"id": "evt_01HQSSO001ABC",
"type": "sso.provider_added",
"timestamp": "2024-01-16T09:00:00.000Z",
"tenant_id": "tnt_acme123",
"application_id": null,
"data": {
"provider_id": "sso_google001",
"tenant_id": "tnt_acme123",
"provider_type": "google",
"display_name": "Sign in with Google",
"is_enabled": true,
"created_by_sub": "usr_admin001",
"created_at": "2024-01-16T09:00:00.000Z",
"config": {
"client_id": "123456789.apps.googleusercontent.com",
"domains": ["acme.com"],
"attribute_mapping": {
"email": "email",
"given_name": "given_name",
"family_name": "family_name",
"picture": "picture"
}
}
}
}
Handler behavior:
// Handler creates SSO provider record
await prisma.ssoProvider.create({
data: {
id: 'sso_google001',
organizationId: 'tnt_acme123',
providerType: 'google',
displayName: 'Sign in with Google',
isEnabled: true,
createdBySub: 'usr_admin001',
clientId: '123456789.apps.googleusercontent.com',
domains: ['acme.com'],
attributeMapping: {
email: 'email',
given_name: 'given_name',
family_name: 'family_name',
picture: 'picture',
},
syncedAt: new Date(),
},
});
sso.provider_updated¶
Fires when SSO provider settings change.
{
"id": "evt_01HQSSO002DEF",
"type": "sso.provider_updated",
"timestamp": "2024-01-20T11:00:00.000Z",
"tenant_id": "tnt_acme123",
"application_id": null,
"data": {
"provider_id": "sso_google001",
"tenant_id": "tnt_acme123",
"provider_type": "google",
"display_name": "Sign in with Google Workspace",
"is_enabled": true,
"changed_fields": ["display_name", "config.domains"],
"previous_values": {
"display_name": "Sign in with Google",
"config.domains": ["acme.com"]
},
"updated_by_sub": "usr_admin001",
"config": {
"client_id": "123456789.apps.googleusercontent.com",
"domains": ["acme.com", "acme.io"],
"attribute_mapping": {
"email": "email",
"given_name": "given_name",
"family_name": "family_name",
"picture": "picture"
}
}
}
}
Handler behavior:
// Handler updates changed SSO configuration
await prisma.ssoProvider.update({
where: { id: 'sso_google001' },
data: {
displayName: 'Sign in with Google Workspace',
domains: ['acme.com', 'acme.io'],
syncedAt: new Date(),
},
});
sso.provider_removed¶
Fires when an SSO provider is disconnected from a tenant.
{
"id": "evt_01HQSSO003GHI",
"type": "sso.provider_removed",
"timestamp": "2024-02-01T14:00:00.000Z",
"tenant_id": "tnt_acme123",
"application_id": null,
"data": {
"provider_id": "sso_okta001",
"tenant_id": "tnt_acme123",
"provider_type": "okta",
"display_name": "Okta SSO",
"removed_by_sub": "usr_admin001",
"removed_at": "2024-02-01T14:00:00.000Z"
}
}
Handler behavior:
// Handler deletes SSO provider record
await prisma.ssoProvider.delete({
where: { id: 'sso_okta001' },
});
Event Summary¶
| Event | Affects | Key Fields |
|---|---|---|
tenant.created | New organization | All tenant fields, created_by_sub |
tenant.updated | Existing organization | changed_fields, previous_values |
tenant.deleted | Organization record | Deletes record (cascades) |
tenant.suspended | Organization status | status = 'suspended', reason |
application.created | New application | All app config, created_by_sub |
application.updated | Existing application | changed_fields, previous_values |
application.deleted | Application record | Deletes record |
sso.provider_added | New SSO provider | Provider config, domains |
sso.provider_updated | Existing SSO provider | changed_fields, previous_values |
sso.provider_removed | SSO provider record | Deletes record |
Related Documentation¶
- Organization Sync Overview
- Prisma Schema
- Use Cases
- Webhook Event Types - All webhook events