Skip to main content

Overview

Risk analysis webhook events allow you to receive real-time notifications when a risk matrix is executed on an entity (person or company) or on a transaction. Gu1 sends HTTP POST requests to your configured webhook endpoint after each risk analysis completes, so you can sync risk scores with external systems, feed BI tools, or trigger workflows.

Why Use Risk Analysis Events?

Risk Score Sync

Keep external systems updated with the latest risk scores

Workflow Automation

Trigger processes when analysis completes (e.g. escalation, reporting)

Audit Trail

Log every risk matrix execution for compliance

Analytics & BI

Feed risk results into dashboards and reports

Available Events

Event TypeDescriptionWhen Triggered
risk_analysis_entity_executedRisk matrix run on person or companyWhen a risk matrix is executed on a person or company (manual run or automatic: entity_created, enrichment_completed, etc.)
risk_analysis_transaction_executedRisk matrix run on transactionWhen a risk matrix is executed on a transaction (e.g. on create/update with rules applied)
Trigger location: apps/api/src/services/rules-execution.service.ts (after successful rules engine execution).

Event Payload Structure

All risk analysis webhooks follow this structure:
{
  "event": "risk_analysis_entity_executed",
  "timestamp": "2025-02-19T14:00:00.000Z",
  "organizationId": "org-uuid",
  "payload": {
    "entity": {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "type": "person",
      "name": "John Doe",
      "taxId": "123-45-6789",
      "externalId": "customer_abc123"
    },
    "rulesExecutionSummary": {
      "rulesHit": [],
      "rulesNoHit": [],
      "totalScore": 25,
      "scoreResult": { "rawScore": 25, "normalizedScore": 35, "label": { "name": "Medium", "range": "30-80" } },
      "riskMatrixName": "Default Entity Matrix",
      "executionTimeMs": 120,
      "trigger": "entity_created",
      "matchedRulesCount": 0
    },
    "riskScore": 25,
    "totalRules": 10,
    "successfulRules": 10,
    "executionTimeMs": 120,
    "triggerEvent": "entity_created",
    "riskMatrixName": "Default Entity Matrix",
    "auditId": "audit-uuid"
  }
}

Key Payload Fields

entity
object
The entity that was analyzed: id, type (person | company | transaction), name, taxId, externalId
rulesExecutionSummary
object
Summary of rule execution: rulesHit, rulesNoHit, actionsExecuted (optional), totalScore, scoreResult, riskMatrixName, executionTimeMs, trigger, matchedRulesCount. May be null. Full structure and example: Rules Execution Summary.
riskScore
number
Final risk score from the risk matrix execution
totalRules
number
Total number of rules evaluated
successfulRules
number
Number of rules that ran successfully
executionTimeMs
number
Execution time of the risk analysis in milliseconds
triggerEvent
string
What triggered the analysis (e.g. entity_created, enrichment_completed, manual)
riskMatrixName
string
Name of the risk matrix that was executed, or null
auditId
string
ID of the risk analysis audit record, or null

risk_analysis_entity_executed

Sent when a risk matrix is executed on a person or company entity. When it fires:
  • Manual risk analysis from the dashboard
  • Automatic trigger on entity creation (when rules are applied)
  • After enrichment completes (when configured to run rules)
  • Other automatic triggers that run the rules engine on an entity
Payload: Same structure as above; entity.type is person or company.

risk_analysis_transaction_executed

Sent when a risk matrix is executed on a transaction. When it fires:
  • Transaction created or updated with rules applied
  • Any flow that runs the rules engine on a transaction
Payload: Same structure; entity.type is transaction. For transactions, entity.name is typically the transaction external ID or identifier.

Code Example

Node.js – Handling Risk Analysis Events

app.post('/webhooks/gu1', async (req, res) => {
  try {
    const signature = req.headers['x-webhook-signature'];
    const rawBody = req.rawBody || JSON.stringify(req.body);
    if (!verifySignature(rawBody, signature, process.env.GU1_WEBHOOK_SECRET)) {
      return res.status(401).json({ error: 'Invalid signature' });
    }

    const { event, payload } = req.body;

    if (event === 'risk_analysis_entity_executed' || event === 'risk_analysis_transaction_executed') {
      await handleRiskAnalysisCompleted(event, payload);
    }

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

async function handleRiskAnalysisCompleted(event, payload) {
  const { entity, riskScore, riskMatrixName, auditId, triggerEvent } = payload;

  // Sync risk score to your system
  await db.entities.update({
    where: { externalId: entity.externalId },
    data: {
      riskScore,
      riskMatrixName,
      lastRiskAnalysisAt: new Date(),
      lastTriggerEvent: triggerEvent,
    },
  });

  // Optional: trigger workflows for high risk
  if (riskScore >= 75) {
    await compliance.queueReview(entity.id, riskScore, auditId);
  }
}

Best Practices

  • Idempotency: Use entity.id + auditId (or timestamp) to avoid processing the same analysis twice.
  • Verify signature: Always validate X-Webhook-Signature as described in the security guide.
  • Respond quickly: Return 200 as soon as you receive the webhook; process asynchronously if needed.

Next Steps