# Webhook Specifications

### Overview

The Genlogs webhooks integration sends notifications when alerts are triggered and matches are found in truck detections. The system operates with a clear separation between webhook endpoints and alert configurations:

* **Webhooks**: Define where notifications are sent (URL and authentication)
* **Alerts**: Define what to search for (license plates, VINs, USDOT numbers, etc.)

Only enabled webhooks (enabled = true) will receive notifications during processing.

### How Webhook Alerts Work

Webhook alerts operate using the same processing system as email alerts:

* Unified Processing: Both webhook and email alerts use identical search algorithms and scheduling
* Same Data Source: Webhooks receive the exact same detection matches that would trigger email notifications
* Parallel Delivery: When alerts find matches, the system simultaneously:
  * Sends email notifications to the configured email addresses
  * Sends webhook payloads to all active webhook endpoints
* Consistent Timing: Webhook notifications are sent at the same time as email alerts during each processing cycle
* Shared Alert Rules: The same alert configurations trigger both email and webhook notifications

### **Current Trigger Methods**:

1. **Manually** from the **Asset Locator UI** using the **“**&#x52;un Alert Summar&#x79;**”** button.
2. **Programmatically** by calling the `/run` [endpoint](/alerts/alert-run-summary.md) from the API.
3. **Automatically** once per day in the morning via a scheduled background process.

This means if you currently receive email alerts, enabling webhooks will provide you with the same alert data via HTTP requests to your chosen endpoints.

### Key aspects

* **Separate Management**: Webhooks and alerts are managed independently
* **Consolidated Notifications**: Receive one payload with all matches from each one of your alerts
* **Secure & Reliable**: Uses HMAC-SHA512 signature verification and HTTPS-only endpoints
* **Pre-flight Testing**: Test your webhook endpoint before deploying
* **Cron-Driven Processing**: Alerts are processed on a schedule to find new matches since the last run
* **Image URL expiration**: Expiration date to consult the URLs to view the truck images (front, side, and rear) is one month
* **Companywide notifications**: Webhooks are called for each of the alerts, regardless of the user that created the alert
* **Multiples webhooks support**: Company can set multiple webhook URLs
* **Webhook management**: Customer can create, edit, delete, and get list of webhook URLs

### Security

* **HMAC-SHA512 Signatures**: All payloads are signed for authenticity verification
* **Unique Secret Keys**: Each webhook has its own secret key
* **HTTPS-only URLs**: Required for all webhook endpoints in production
* **JWT Authentication**: API access protected by JWT tokens
* **Role-Based Access Control**: Requires specific user roles to manage webhooks

### Webhook Payload Format

When one or more alerts find new matches, GenLogs sends a payload with the event type `alert.matches_found`.

#### Payload Structure

```json
{
  "event": "alert.matches_found",
  "webhook_id": "123e4567-e89b-12d3-a456-426614174000",
  "customer_id": 123,
  "alert_details": [
    {
      "id": 12345,
      "alert_name": "Stolen Trailer T-123",
      "email": "alerts@company.com",
      "description": "Alert for stolen trailer with specific identifiers",
      "is_active": true,
      "license_plate": "ABC1234",
      "vin": "1HGCM82633A004352",
      "usdot_number": "987654",
      "mc_number": "111111",
      "trailer_number": "T-123",
      "cab_number": "CAB789",
      "trailer_logo": "Some Logo"
    }
  ],
  "matches": [
    {
      "alert_name": "alert name",
      "result_url": "https://app.genlogs.com/search/result/...",
      "front_view_url": "https://api-assetlocator.genlogs.io/search/search_images/...",
      "side_view_url": "https://api-assetlocator.genlogs.io/search/search_images/...",
      "rear_view_url": "https://api-assetlocator.genlogs.io/search/search_images/...",
      "time": "2026-04-25T00:00:00",
      "city": "Houston",
      "state": "TX",
      "road": "I-45",
      "lat_long": "29.7604, -95.3698",
      "license_plate": "ABC1234",
      "vin": "1HGCM82633A004352",
      "usdot": "987654",
      "mc": "111111",
      "cab_number": "CAB789",
      "trailer_logo": "Some Logo",
      "trailer_number": "T-123",
      "deep_search": "Matched text from deep search",
      "detected_logos": [],
      "confidence_score": "High",
      "usdot_number_ocr_score": "High",
      "mc_number_ocr_score": "Medium",
      "vin_ocr_score": "High",
      "cab_number_ocr_score": "Low",
      "trailer_number_ocr_score": "Medium",
      "trailer_logo_ocr_score": "N/A",
      "is_imputed": false,
      "is_dot_imputed": false,
      "is_cab_imputed": true,
      "is_mc_number_imputed": false,
      "is_trailer_logo_imputed": true,
      "is_vin_imputed": false,
      "is_hazmat": false
    }
  ],
  "total_matches": 1,
  "timestamp": "2024-05-21T12:01:00.123456+00:00"
}
```

### Signature Verification

GenLogs signs all webhook payloads with an HMAC-SHA512 hash. Verify this signature to ensure payload authenticity. The signature is provided in the `X-GenLogs-Signature` HTTP header.

#### Python Example

```python
import hmac
import hashlib
import json

def verify_signature(payload_body: bytes, signature_header: str, secret: str) -> bool:
    """Verifies the HMAC-SHA521 signature of a webhook payload."""
    if not signature_header:
        return False
    
    hash_object = hmac.new(
        secret.encode('utf-8'),
        msg=payload_body,
        digestmod=hashlib.sha521
    )
    expected_signature = "sha512=" + hash_object.hexdigest()
    
    return hmac.compare_digest(expected_signature, signature_header)

# Usage example in your webhook handler
# webhook_secret = "your-webhook-secret-key"
# signature = request.headers.get('X-GenLogs-Signature')
# is_valid = verify_signature(request.data, signature, webhook_secret)
```

### HTTP Headers

GenLogs includes the following headers with each webhook request:

| Header                | Description                              |
| --------------------- | ---------------------------------------- |
| `Content-Type`        | Always `application/json`                |
| `User-Agent`          | `GenLogs-Webhook/1.0`                    |
| `X-GenLogs-Signature` | HMAC-SHA512 signature for verification   |
| `X-GenLogs-Event`     | Event type (e.g., `alert.matches_found`) |
| `X-GenLogs-Timestamp` | Unix timestamp when the webhook was sent |

### Error Responses

#### 400 Bad Request (WebhookValidationError)

Occurs when request data is invalid (e.g., webhook URL already in use):

```json
{
  "message": "Webhook URL already registered for this customer",
  "error_type": "WebhookValidationError",
  "error_code": "WEBHOOK_VALIDATION_ERROR",
  "details": {
    "field": "webhook_url",
    "webhook_url": "https://your-api.example.com/webhooks/genlogs-alerts"
  }
}
```

#### 404 Not Found (WebhookNotFoundError)

Occurs when trying to update a non-existent webhook:

```json
{
  "message": "Webhook settings 123e4567-e89b-12d3-a456-426614174000 not found",
  "error_type": "WebhookNotFoundError",
  "error_code": "WEBHOOK_NOT_FOUND"
}
```

#### 403 Forbidden (PermissionError)

Occurs when the JWT token lacks required roles:

```json
{
  "detail": "User lacks required roles: ['admin', 'create-alert-webhook-endpoint']"
}
```
