# 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](https://docs.genlogs.io/alerts/alert-run-summary) 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

{% hint style="info" %}

#### Imputed Fields

Fields **is\_usdot\_imputed**, **is\_cab\_imputed**, **is\_mc\_imputed**, **is\_trailer\_logo\_imputed** and **is\_vin\_imputed** represent whether the corresponding field value was inferred or auto-filled by the system rather than directly observed.

These fields are boolean and help differentiate between raw observations and system-generated estimations.

*\*this feature requires permission access*
{% endhint %}

{% hint style="info" %}

#### OCR Score Fields

Fields **usdot\_number\_ocr\_score**, **mc\_number\_ocr\_score**, **vin\_ocr\_score**, **cab\_number\_ocr\_score**, **trailer\_number\_ocr\_score**, and **trailer\_logo\_ocr\_score** represent the **OCR** reading reliability classification for their associated fields.\
For example, **usdot\_number\_ocr\_score** represents the confidence level for the **usdot\_number** field.

**Possible values are**:

* **High** – The OCR result has a high level of confidence.
* **Medium** – The OCR result has a moderate level of confidence; manual verification may be required.
* **Low** – The OCR result has a low level of confidence; manual review is recommended.
* **N/A** – No OCR score is available for this field.

*\*this feature requires permission access*
{% endhint %}

{% hint style="info" %}

#### Hazmat Indicator Field

**Field:** `is_hazmat`

The `is_hazmat` field indicates whether the carrier is identified as operating hazardous materials (HAZMAT). This value represents the system’s determination based on available carrier data and regulatory signals.

**Possible values:**

* `true` – The carrier is identified as operating hazardous materials.
* `false` – The carrier is not identified as operating hazardous materials.

*\*this feature requires permission access*
{% endhint %}

```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": "2024-05-21T12:00:00+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",
      "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"
}

```

#### Payload Fields

| Field           | Type    | Description                               |
| --------------- | ------- | ----------------------------------------- |
| `event`         | string  | Always `"alert.matches_found"`            |
| `webhook_id`    | string  | UUID of the webhook configuration         |
| `customer_id`   | integer | Customer ID associated with the alerts    |
| `alert_details` | array   | Details of all alerts that found matches  |
| `matches`       | array   | All detection matches found               |
| `total_matches` | integer | Total number of matches across all alerts |
| `timestamp`     | string  | ISO timestamp when the webhook was sent   |

#### Alert Details Object

| Field            | Type    | Description                      |
| ---------------- | ------- | -------------------------------- |
| `id`             | int     | ID of the alert                  |
| `alert_name`     | string  | Name of the alert                |
| `email`          | string  | Contact email for the alert      |
| `description`    | string  | Alert description                |
| `is_active`      | boolean | Whether the alert is active      |
| `license_plate`  | string  | License plate criteria (if any)  |
| `vin`            | string  | VIN criteria (if any)            |
| `usdot_number`   | string  | USDOT number criteria (if any)   |
| `mc_number`      | string  | MC number criteria (if any)      |
| `trailer_number` | string  | Trailer number criteria (if any) |
| `cab_number`     | string  | Cab number criteria (if any)     |
| `trailer_logo`   | string  | Trailer logo criteria (if any)   |

#### Match Object Fields

| Field                       | Type              | Description                                                                                                                                     |
| --------------------------- | ----------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| alert\_name                 | string            | Name of the alert that generated the match.                                                                                                     |
| result\_url                 | string            | URL to the search result in the Genlogs application.                                                                                            |
| front\_view\_url            | string            | URL of the front-view image associated with the match.                                                                                          |
| side\_view\_url             | string            | URL of the side-view image associated with the match.                                                                                           |
| rear\_view\_url             | string            | URL of the rear-view image associated with the match.                                                                                           |
| time                        | string (ISO 8601) | Timestamp when the match was detected.                                                                                                          |
| city                        | string            | City where the match was detected.                                                                                                              |
| state                       | string            | State where the match was detected.                                                                                                             |
| road                        | string            | Road or highway where the match was detected.                                                                                                   |
| lat\_long                   | string            | Latitude and longitude of the detection location.                                                                                               |
| license\_plate              | string            | Detected license plate number.                                                                                                                  |
| vin                         | string            | Detected Vehicle Identification Number (VIN).                                                                                                   |
| usdot                       | string            | Detected USDOT number.                                                                                                                          |
| mc                          | string            | Detected MC number.                                                                                                                             |
| cab\_number                 | string            | Detected cab number.                                                                                                                            |
| trailer\_number             | string            | Detected trailer number.                                                                                                                        |
| trailer\_logo               | string            | Detected trailer logo text or label.                                                                                                            |
| deep\_search                | string            | Text matched through deep search processing.                                                                                                    |
| confidence\_score           | string            | Overall confidence classification for the match, aligned with `/visual-sightings/carrier-observations` values (e.g. `High`, `Medium`, `Low`).   |
| usdot\_number\_ocr\_score   | string            | OCR confidence score for the detected USDOT number (`High`, `Medium`, `Low`, `N/A`). *Requires permission access.*                              |
| mc\_number\_ocr\_score      | string            | OCR confidence score for the detected MC number (`High`, `Medium`, `Low`, `N/A`). *Requires permission access.*                                 |
| vin\_ocr\_score             | string            | OCR confidence score for the detected VIN (`High`, `Medium`, `Low`, `N/A`). *Requires permission access.*                                       |
| cab\_number\_ocr\_score     | string            | OCR confidence score for the detected cab number (`High`, `Medium`, `Low`, `N/A`). *Requires permission access.*                                |
| trailer\_number\_ocr\_score | string            | OCR confidence score for the detected trailer number (`High`, `Medium`, `Low`, `N/A`). *Requires permission access.*                            |
| trailer\_logo\_ocr\_score   | string            | OCR confidence score for the detected trailer logo (`High`, `Medium`, `Low`, `N/A`). *Requires permission access.*                              |
| is\_imputed                 | boolean           | Indicates whether any field in the match was inferred or auto-filled by the system rather than directly observed. *Requires permission access.* |
| is\_dot\_imputed            | boolean           | Indicates whether the USDOT number value was imputed by the system. *Requires permission access.*                                               |
| is\_cab\_imputed            | boolean           | Indicates whether the cab number value was imputed by the system. *Requires permission access.*                                                 |
| is\_mc\_number\_imputed     | boolean           | Indicates whether the MC number value was imputed by the system. *Requires permission access.*                                                  |
| is\_trailer\_logo\_imputed  | boolean           | Indicates whether the trailer logo value was imputed by the system. *Requires permission access.*                                               |
| is\_vin\_imputed            | boolean           | Indicates whether the VIN value was imputed by the system. *Requires permission access.*                                                        |
| hazmat                      | boolean \| string | Hazmat detection result as stored by the detection system (boolean or label).                                                                   |
| is\_hazmat                  | boolean           | Normalized indicator specifying whether the detected carrier is classified as hazmat.                                                           |

### 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']"
}
```
