> ## Documentation Index
> Fetch the complete documentation index at: https://docs.gu1.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Risk Analysis Webhook Events

> Receive real-time notifications when a risk analysis (risk matrix execution) completes — with gu1 webhook events for real-time downstream integration.

## 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?

<CardGroup cols={2}>
  <Card title="Risk Score Sync" icon="chart-line">
    Keep external systems updated with the latest risk scores
  </Card>

  <Card title="Workflow Automation" icon="robot">
    Trigger processes when analysis completes (e.g. escalation, reporting)
  </Card>

  <Card title="Audit Trail" icon="clipboard-list">
    Log every risk matrix execution for compliance
  </Card>

  <Card title="Analytics & BI" icon="database">
    Feed risk results into dashboards and reports
  </Card>
</CardGroup>

## Available Events

| Event Type                           | Description                          | When Triggered                                                                                                                        |
| ------------------------------------ | ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------- |
| `risk_analysis_entity_executed`      | Risk matrix run on person or company | When a risk matrix is executed on a **person** or **company** (manual run or automatic: entity\_created, enrichment\_completed, etc.) |
| `risk_analysis_transaction_executed` | Risk matrix run on transaction       | When 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:

```json theme={null}
{
  "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

<ResponseField name="entity" type="object">
  The entity that was analyzed: `id`, `type` (person | company | transaction), `name`, `taxId`, `externalId`
</ResponseField>

<ResponseField name="rulesExecutionSummary" type="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](/en/api-reference/rules-execution-summary).
</ResponseField>

<ResponseField name="riskScore" type="number">
  Final risk score from the risk matrix execution
</ResponseField>

<ResponseField name="totalRules" type="number">
  Total number of rules evaluated
</ResponseField>

<ResponseField name="successfulRules" type="number">
  Number of rules that ran successfully
</ResponseField>

<ResponseField name="executionTimeMs" type="number">
  Execution time of the risk analysis in milliseconds
</ResponseField>

<ResponseField name="triggerEvent" type="string">
  What triggered the analysis (e.g. `entity_created`, `enrichment_completed`, `manual`)
</ResponseField>

<ResponseField name="riskMatrixName" type="string">
  Name of the risk matrix that was executed, or null
</ResponseField>

<ResponseField name="auditId" type="string">
  ID of the risk analysis audit record, or null
</ResponseField>

## 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

```javascript theme={null}
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](/en/webhooks/security).
* **Respond quickly**: Return 200 as soon as you receive the webhook; process asynchronously if needed.

## Next Steps

<CardGroup cols={2}>
  <Card title="Entity Events" icon="user" href="/en/webhooks/events/entity-events">
    Handle entity lifecycle events
  </Card>

  <Card title="Transaction Events" icon="credit-card" href="/en/webhooks/events/transaction-events">
    Process transaction webhooks
  </Card>

  <Card title="Webhook Security" icon="shield" href="/en/webhooks/security">
    Secure your webhook endpoints
  </Card>

  <Card title="Configuration" icon="gear" href="/en/webhooks/configuration">
    Configure webhook settings
  </Card>
</CardGroup>
