Skip to main content

Overview

Rule webhook events allow you to receive real-time notifications when compliance or business rules are triggered for entities in the Gu1 platform. These events enable you to automate compliance actions, alert your team, and maintain audit trails when risk conditions are detected.

Why Use Rule Events?

Real-Time Compliance

Get instant alerts when risk rules are triggered

Automated Actions

Automatically block, flag, or escalate entities

Audit Trail

Track all rule triggers for compliance reporting

Risk Management

Respond to high-risk conditions immediately

Available Events

rule.triggered

The rule.triggered event is fired when a compliance or business rule evaluates to true for an entity. When it fires:
  • A rule condition is met during entity creation or update
  • Periodic rule evaluation detects a match
  • Transaction monitoring rules identify suspicious activity
  • Compliance checks (PEP, sanctions, adverse media) return positive matches
Filters available:
  • ruleIds: Only receive events for specific rules
  • ruleSeverity: Filter by severity level (low, medium, high, critical)
  • entityTypes: Filter by entity type

Event Payload

rule.triggered Payload

{
  "event": "rule.triggered",
  "timestamp": "2025-01-07T14:00:00.000Z",
  "payload": {
    "ruleId": "550e8400-e29b-41d4-a716-446655440000",
    "rule": {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "name": "High Risk Country Check",
      "description": "Flags entities from high-risk countries",
      "severity": "high",
      "category": "geographic_risk",
      "isActive": true
    },
    "entityId": "123e4567-e89b-12d3-a456-426614174000",
    "entity": {
      "id": "123e4567-e89b-12d3-a456-426614174000",
      "externalId": "customer_xyz789",
      "name": "John Doe",
      "type": "person",
      "countryCode": "KP",
      "status": "blocked"
    },
    "evaluationId": "eval_abc123",
    "triggerData": {
      "countryCode": "KP",
      "riskLevel": "critical",
      "matchedCriteria": [
        "sanctioned_country",
        "high_risk_jurisdiction"
      ],
      "additionalInfo": {
        "sanctionList": ["OFAC", "UN"],
        "riskScore": 95
      }
    },
    "action": {
      "type": "block",
      "reason": "Entity from sanctioned country",
      "automaticAction": true,
      "previousStatus": "under_review",
      "newStatus": "blocked"
    },
    "triggeredAt": "2025-01-07T14:00:00.000Z"
  }
}

Key Payload Fields

ruleId
string
Unique identifier of the triggered rule
rule
object
Complete rule information including name, description, severity, and category
rule.severity
string
Severity level: low, medium, high, or critical
entityId
string
The entity that triggered the rule
entity
object
Complete entity information including your externalId
evaluationId
string
Unique identifier for this rule evaluation
triggerData
object
Data that caused the rule to trigger, including matched criteria and risk scores
action
object
Action taken as a result of the rule trigger (optional)
action.type
string
Action type: block, flag, review, alert, or none
action.automaticAction
boolean
Whether the action was taken automatically by Gu1

Rule Categories and Examples

Geographic Risk Rules

Triggered when entities are from high-risk countries or jurisdictions:
{
  "rule": {
    "name": "Sanctioned Country Check",
    "category": "geographic_risk",
    "severity": "critical"
  },
  "triggerData": {
    "countryCode": "IR",
    "sanctionList": ["OFAC", "EU"],
    "riskLevel": "critical"
  },
  "action": {
    "type": "block",
    "automaticAction": true
  }
}

PEP (Politically Exposed Person) Rules

Triggered when entity matches PEP databases:
{
  "rule": {
    "name": "PEP Screening",
    "category": "pep_check",
    "severity": "high"
  },
  "triggerData": {
    "pepStatus": "confirmed",
    "position": "Former Government Official",
    "country": "XX",
    "matchConfidence": 0.95,
    "source": "World-Check"
  },
  "action": {
    "type": "review",
    "automaticAction": true
  }
}

Sanctions Screening Rules

Triggered when entity appears on sanctions lists:
{
  "rule": {
    "name": "OFAC Sanctions Screening",
    "category": "sanctions",
    "severity": "critical"
  },
  "triggerData": {
    "matchType": "exact",
    "sanctionList": "OFAC SDN",
    "matchedName": "John Doe",
    "listingDate": "2020-01-15",
    "program": "Counter Terrorism"
  },
  "action": {
    "type": "block",
    "automaticAction": true
  }
}

Transaction Monitoring Rules

Triggered by suspicious transaction patterns:
{
  "rule": {
    "name": "High Velocity Transactions",
    "category": "transaction_monitoring",
    "severity": "medium"
  },
  "triggerData": {
    "transactionCount": 15,
    "totalAmount": 150000,
    "timeWindow": "24h",
    "averageAmount": 10000,
    "threshold": 10
  },
  "action": {
    "type": "flag",
    "automaticAction": true
  }
}

Adverse Media Rules

Triggered when negative news is found:
{
  "rule": {
    "name": "Adverse Media Screening",
    "category": "adverse_media",
    "severity": "high"
  },
  "triggerData": {
    "matchCount": 3,
    "categories": ["fraud", "financial crime"],
    "sources": ["Reuters", "Financial Times"],
    "latestDate": "2024-12-15",
    "relevanceScore": 0.85
  },
  "action": {
    "type": "review",
    "automaticAction": true
  }
}

Filter Configuration

Filter by Rule ID

Only receive events for specific rules:
{
  "eventTypes": ["rule.triggered"],
  "filters": {
    "ruleIds": [
      "rule_sanctions_ofac",
      "rule_high_risk_country"
    ]
  }
}

Filter by Severity

Only receive high and critical severity alerts:
{
  "eventTypes": ["rule.triggered"],
  "filters": {
    "ruleSeverity": ["high", "critical"]
  }
}

Filter by Entity Type

Only receive rules triggered for persons:
{
  "eventTypes": ["rule.triggered"],
  "filters": {
    "entityTypes": ["person"]
  }
}

Combined Filters

Combine multiple filters for precise control:
{
  "eventTypes": ["rule.triggered"],
  "filters": {
    "entityTypes": ["person"],
    "ruleSeverity": ["critical"],
    "ruleIds": ["rule_sanctions_ofac", "rule_pep_screening"]
  }
}

Code Examples

Node.js - Handling Rule Events

const express = require('express');
const app = express();

app.use(express.json({
  verify: (req, res, buf) => {
    req.rawBody = buf.toString('utf8');
  }
}));

app.post('/webhooks/rules', async (req, res) => {
  try {
    // Verify signature (see security guide)
    if (!verifySignature(req.rawBody, req.headers['x-webhook-signature'])) {
      return res.status(401).json({ error: 'Invalid signature' });
    }

    const { event, payload } = req.body;

    if (event === 'rule.triggered') {
      await handleRuleTriggered(payload);
    }

    res.status(200).json({ success: true });
  } catch (error) {
    console.error('Webhook error:', error);
    res.status(500).json({ error: error.message });
  }
});

async function handleRuleTriggered(payload) {
  const { rule, entity, triggerData, action, evaluationId } = payload;

  console.log(`Rule triggered: ${rule.name} for ${entity.name}`);

  // Log rule trigger
  await db.ruleTriggers.create({
    data: {
      ruleId: rule.id,
      ruleName: rule.name,
      entityId: entity.id,
      externalId: entity.externalId,
      severity: rule.severity,
      triggerData,
      evaluationId,
      triggeredAt: new Date()
    }
  });

  // Handle based on severity
  switch (rule.severity) {
    case 'critical':
      await handleCriticalRule(rule, entity, triggerData, action);
      break;

    case 'high':
      await handleHighSeverityRule(rule, entity, triggerData, action);
      break;

    case 'medium':
      await handleMediumSeverityRule(rule, entity, triggerData, action);
      break;

    case 'low':
      await handleLowSeverityRule(rule, entity, triggerData, action);
      break;
  }

  // Handle based on action type
  if (action) {
    switch (action.type) {
      case 'block':
        await handleBlockAction(entity, action);
        break;

      case 'review':
        await handleReviewAction(entity, rule, action);
        break;

      case 'flag':
        await handleFlagAction(entity, rule, action);
        break;

      case 'alert':
        await handleAlertAction(entity, rule, action);
        break;
    }
  }
}

async function handleCriticalRule(rule, entity, triggerData, action) {
  console.log(`🚨 CRITICAL: ${rule.name} triggered for ${entity.name}`);

  // Immediately block entity if not already blocked
  if (entity.status !== 'blocked') {
    await blockEntity(entity.id, rule.name);
  }

  // Alert compliance team immediately
  await slack.send({
    channel: '#compliance-critical',
    priority: 'critical',
    message: `🚨 CRITICAL RULE TRIGGERED`,
    fields: {
      'Rule': rule.name,
      'Entity': entity.name,
      'External ID': entity.externalId,
      'Severity': rule.severity,
      'Action Taken': action?.type || 'none',
      'Details': JSON.stringify(triggerData, null, 2)
    }
  });

  // Create high-priority case
  await compliance.createCase({
    entityId: entity.id,
    ruleId: rule.id,
    priority: 'critical',
    type: 'rule_trigger',
    data: { rule, entity, triggerData, action },
    assignTo: 'compliance-lead'
  });

  // Send to external monitoring system
  await monitoring.alert({
    level: 'critical',
    title: `Rule Triggered: ${rule.name}`,
    entity: entity.externalId,
    rule: rule.name,
    data: triggerData
  });
}

async function handleHighSeverityRule(rule, entity, triggerData, action) {
  console.log(`⚠️ HIGH: ${rule.name} triggered for ${entity.name}`);

  // Flag entity for review
  await flagEntity(entity.id, rule.name, 'high');

  // Alert compliance team
  await slack.send({
    channel: '#compliance-alerts',
    message: `⚠️ High severity rule triggered: ${rule.name}`,
    fields: {
      'Entity': entity.name,
      'External ID': entity.externalId,
      'Rule': rule.name,
      'Action': action?.type || 'none'
    }
  });

  // Create case for review
  await compliance.createCase({
    entityId: entity.id,
    ruleId: rule.id,
    priority: 'high',
    type: 'rule_trigger',
    data: { rule, entity, triggerData }
  });
}

async function handleBlockAction(entity, action) {
  console.log(`Blocking entity: ${entity.name}`);

  // Update local database
  await db.entities.update({
    where: { gu1Id: entity.id },
    data: {
      status: 'blocked',
      blockedAt: new Date(),
      blockReason: action.reason
    }
  });

  // Disable user access
  await auth.disableUser(entity.externalId);

  // Notify entity (if required by regulations)
  await email.send({
    to: entity.attributes?.email,
    subject: 'Account Status Update',
    template: 'account-blocked',
    data: {
      name: entity.name,
      reason: action.reason,
      supportUrl: 'https://support.example.com'
    }
  });
}

async function handleReviewAction(entity, rule, action) {
  console.log(`Flagging for review: ${entity.name}`);

  // Create review task
  await tasks.create({
    type: 'compliance_review',
    entityId: entity.id,
    priority: rule.severity === 'high' ? 'high' : 'normal',
    title: `Review: ${rule.name} triggered`,
    description: action.reason,
    assignedTo: 'compliance-team',
    dueDate: new Date(Date.now() + 24 * 60 * 60 * 1000) // 24 hours
  });
}

app.listen(3000);

Python - Handling Rule Events

from flask import Flask, request, jsonify
import logging

app = Flask(__name__)

@app.route('/webhooks/rules', methods=['POST'])
def rules_webhook():
    try:
        # Verify signature (see security guide)
        signature = request.headers.get('X-Webhook-Signature')
        raw_body = request.get_data(as_text=True)

        if not verify_signature(raw_body, signature):
            return jsonify({'error': 'Invalid signature'}), 401

        # Parse webhook
        payload = request.json
        event = payload['event']
        data = payload['payload']

        if event == 'rule.triggered':
            handle_rule_triggered(data)

        return jsonify({'success': True}), 200

    except Exception as e:
        logging.error(f'Webhook error: {e}')
        return jsonify({'error': str(e)}), 500

def handle_rule_triggered(data):
    rule = data['rule']
    entity = data['entity']
    trigger_data = data['triggerData']
    action = data.get('action')

    logging.info(f"Rule triggered: {rule['name']} for {entity['name']}")

    # Log trigger
    db.rule_triggers.insert({
        'rule_id': rule['id'],
        'rule_name': rule['name'],
        'entity_id': entity['id'],
        'external_id': entity['externalId'],
        'severity': rule['severity'],
        'trigger_data': trigger_data,
        'evaluation_id': data['evaluationId']
    })

    # Handle based on severity
    severity_handlers = {
        'critical': handle_critical_rule,
        'high': handle_high_severity_rule,
        'medium': handle_medium_severity_rule,
        'low': handle_low_severity_rule
    }

    handler = severity_handlers.get(rule['severity'])
    if handler:
        handler(rule, entity, trigger_data, action)

    # Handle action
    if action:
        action_handlers = {
            'block': handle_block_action,
            'review': handle_review_action,
            'flag': handle_flag_action,
            'alert': handle_alert_action
        }

        action_handler = action_handlers.get(action['type'])
        if action_handler:
            action_handler(entity, rule, action)

def handle_critical_rule(rule, entity, trigger_data, action):
    logging.critical(f"CRITICAL: {rule['name']} triggered for {entity['name']}")

    # Block entity
    if entity['status'] != 'blocked':
        block_entity(entity['id'], rule['name'])

    # Alert team
    slack.send({
        'channel': '#compliance-critical',
        'message': f"🚨 CRITICAL RULE TRIGGERED: {rule['name']}",
        'fields': {
            'Entity': entity['name'],
            'External ID': entity['externalId'],
            'Severity': rule['severity']
        }
    })

    # Create case
    compliance.create_case({
        'entity_id': entity['id'],
        'rule_id': rule['id'],
        'priority': 'critical',
        'type': 'rule_trigger'
    })

def handle_block_action(entity, rule, action):
    logging.info(f"Blocking entity: {entity['name']}")

    # Update database
    db.entities.update(
        {'gu1_id': entity['id']},
        {
            'status': 'blocked',
            'block_reason': action['reason']
        }
    )

    # Disable access
    auth.disable_user(entity['externalId'])

if __name__ == '__main__':
    app.run(port=3000)

Use Cases

Use Case 1: Automated Compliance Actions

Automatically block high-risk entities:
async function handleRuleTriggered(payload) {
  const { rule, entity, action } = payload;

  if (rule.severity === 'critical' && action?.type === 'block') {
    // Immediately block all services
    await services.blockAll(entity.externalId);

    // Freeze accounts
    await accounts.freezeAll(entity.externalId);

    // Log for audit
    await audit.log({
      action: 'auto_block',
      entityId: entity.id,
      reason: action.reason,
      ruleId: rule.id,
      timestamp: new Date()
    });

    // Alert compliance team
    await notifyCompliance('critical', entity, rule);
  }
}

Use Case 2: Risk Scoring and Monitoring

Update entity risk scores based on rule triggers:
async function updateRiskScore(entity, rule, triggerData) {
  const currentScore = await getRiskScore(entity.id);

  // Add points based on severity
  const severityPoints = {
    low: 10,
    medium: 25,
    high: 50,
    critical: 100
  };

  const newScore = currentScore + severityPoints[rule.severity];

  await db.entities.update({
    where: { gu1Id: entity.id },
    data: {
      riskScore: newScore,
      riskLevel: calculateRiskLevel(newScore),
      lastRiskUpdate: new Date()
    }
  });

  // Trigger additional reviews if score exceeds threshold
  if (newScore > 75) {
    await createEnhancedDueDiligence(entity.id);
  }
}

Use Case 3: Regulatory Reporting

Generate reports for regulatory compliance:
async function generateComplianceReport(entity, rule, triggerData) {
  // Create SAR (Suspicious Activity Report) if required
  if (rule.category === 'transaction_monitoring' && rule.severity === 'high') {
    await reports.createSAR({
      entityId: entity.id,
      entityName: entity.name,
      ruleTriggered: rule.name,
      suspiciousActivity: triggerData,
      filedBy: 'system',
      filedAt: new Date(),
      status: 'pending_review'
    });

    // Notify compliance officer
    await notifyComplianceOfficer({
      type: 'SAR_created',
      entity,
      rule,
      data: triggerData
    });
  }
}

Best Practices

Always log rule triggers for compliance audit trails:
await db.ruleTriggers.create({
  data: {
    ruleId: rule.id,
    entityId: entity.id,
    evaluationId: evaluationId,
    triggerData,
    triggeredAt: new Date(),
    webhook: req.body
  }
});
Implement different workflows based on severity:
  • Critical: Immediate blocking + urgent alerts
  • High: Flag for review + notify compliance team
  • Medium: Queue for periodic review
  • Low: Log only + aggregate reports
Use evaluation ID to prevent duplicate processing:
const processed = await db.webhookLog.findUnique({
  where: { evaluationId: payload.evaluationId }
});

if (processed) {
  return; // Skip duplicate
}
Route alerts based on rule category:
const alertChannels = {
  sanctions: '#compliance-sanctions',
  pep_check: '#compliance-pep',
  transaction_monitoring: '#aml-team',
  adverse_media: '#risk-team',
  geographic_risk: '#compliance-alerts'
};

const channel = alertChannels[rule.category] || '#compliance-general';
await slack.send({ channel, message: alertMessage });
Allow marking false positives for rule tuning:
async function markFalsePositive(evaluationId, reason) {
  await db.ruleTriggers.update({
    where: { evaluationId },
    data: {
      falsePositive: true,
      falsePositiveReason: reason,
      reviewedBy: userId,
      reviewedAt: new Date()
    }
  });

  // Feed back to rule engine for optimization
  await rulesEngine.reportFalsePositive(evaluationId, reason);
}

Troubleshooting

Check:
  • Webhook is subscribed to rule.triggered event
  • Rules are active in Gu1 dashboard
  • Filters match the rule properties
  • Entity type matches your filters
Test: Create a test entity that should trigger a rule and verify the webhook fires.
The triggerData structure varies by rule type and category. Not all fields will be present for all rules.Example: A geographic risk rule won’t have pepStatus, while a PEP rule won’t have sanctionList.
The action field is optional. Some rules may only trigger alerts without automatic actions:
if (payload.action) {
  await handleAction(payload.action);
} else {
  // Rule triggered but no automatic action
  await logRuleTrigger(payload);
}

Next Steps