# Webhooks

<a id="webhooks"></a>

Approximated allows you to receive notifications about events happening with your virtual hosts by sending HTTP GET or POST requests to a URL you control.

Webhooks can be configured from your dashboard by logging in and navigating to the "Webhooks" section. A basic log history for each configured webhook is also available there.

<a id="webhook-configuration"></a>

## Configuring Your Webhooks

Understanding the following configuration options will help you make the most of the webhooks feature and ensure secure and reliable event handling.

<a id="webhook-get-vs-post"></a>

### GET vs POST Requests

When setting up your webhook, you can choose between HTTP GET or POST request methods:

- **POST:** The event data (as shown in the examples below) will be sent as a JSON payload in the request body. Recommended for most cases.
- **GET:** The event data will be URL-encoded and appended as query parameters to your webhook URL.

<a id="webhook-idempotent-keys"></a>

### Idempotent Event Keys

Each webhook event includes an `idempotent_key` in its payload (e.g., `"apx-whl-<integer id>"`). This key is unique for each distinct event instance.

If Approximated needs to retry sending an event, the `idempotent_key` for that specific event instance will remain the same across all retries. You can use this key on your server to detect and deduplicate events, preventing accidental reprocessing of the same event.

<a id="webhook-security-key"></a>

### Security Key Header

For an added layer of security, you can configure each webhook with a secret string key in the dashboard.

If a key is configured, Approximated will include it in every webhook request sent to your endpoint via the `webhook-key` HTTP header. You can then verify this key on your server to ensure that the request genuinely originated from Approximated.

<a id="webhook-endpoints-routing"></a>

### Webhook Endpoints

Approximated offers flexibility in how you route webhook events:

- **Single Webhook, Multiple Events:** You can create a single webhook configuration (pointing to one URL) and have it trigger for multiple different event types (e.g., Virtual Host Created, Virtual Host Deleted). Your endpoint will then need to inspect the `type` and `event` fields in the payload to differentiate and process them accordingly.
- **Multiple Webhooks, Different Endpoints/Events:** Alternatively, you can create several distinct webhook configurations. Each can point to a different URL or the same URL, and each can be configured to trigger for specific, individual events. This allows you to route different event types to different processing logic or microservices if needed.

<a id="webhook-encryption-security"></a>

### Webhook Encryption & Security

Webhooks and their data are intended to be sent only to SSL/TLS encrypted endpoints. Each payload is not separately encrypted, so please ensure that any configured endpoints are setup with SSL/TLS certificates of their own.

<a id="webhook-events"></a>

## Webhook Events

The following webhook events can be configured:

**Event Types**

<a id="webhook-events-virtual-host-created"></a>

### Virtual Host Created

Triggered when a new virtual host is successfully created through the API or dashboard.

**Note:** this event is triggered when a Virtual Host is added to your cluster but does not necessarily mean that the custom domain is successfully connected to the cluster yet.

To be notified of status changes for the custom domain, such as DNS updates or SSL status, please use the [Virtual Host Monitor Updated event](#webhook-events-virtual-host-monitor-updated).

Example event payload:

```json
{
  "idempotent_key": "apx-whl-1234567890",
  "data": {
    "id": 160389,
    "keep_host": null,
    "lb_policy": "first",
    "lb_sticky": true,
    "upstreams": [],
    "lb_enabled": false,
    "target_ports": "443",
    "target_address": "ourapplication.com",
    "incoming_address": "acustomdomain.com"
  },
  "type": "virtual_host",
  "event": "create"
}
```

<a id="webhook-events-virtual-host-updated"></a>

### Virtual Host Updated

Triggered when the configuration of an existing virtual host is updated through the dashboard or API.

**Note:** this event is NOT triggered by monitoring changes like DNS or SSL statuses changing. To be notified of those changes, please use the [Virtual Host Monitor Updated event](#webhook-events-virtual-host-monitor-updated).

Example event payload:

```json
{
  "idempotent_key": "apx-whl-1234567891",
  "data": {
    "id": 1599456,
    "status": "ACTIVE_SSL",
    "apx_hit": true,
    "has_ssl": true,
    "keep_host": null,
    "lb_policy": "first",
    "lb_sticky": true,
    "upstreams": [],
    "created_at": "2025-04-22T22:44:49",
    "lb_enabled": false,
    "is_resolving": true,
    "target_ports": "443",
    "dns_pointed_at": "213.188.215.88",
    "status_message": "Active with SSL",
    "target_address": "ourapp.com",
    "ssl_active_from": "2025-04-22T21:46:24",
    "incoming_address": "acustomdomain.com",
    "ssl_active_until": "2025-07-21T21:46:23",
    "last_monitored_unix": 1745361972
  },
  "type": "virtual_host",
  "event": "update"
}
```

<a id="webhook-events-virtual-host-deleted"></a>

### Virtual Host Deleted

Triggered when a virtual host is successfully deleted.

Example event payload:

```json
{
  "idempotent_key": "apx-whl-1234567892",
  "data": {
    "id": 16054568,
    "keep_host": null,
    "lb_policy": "first",
    "lb_sticky": true,
    "upstreams": [],
    "lb_enabled": false,
    "target_ports": "443",
    "target_address": "ourapp.com",
    "incoming_address": "acustomdomain.com"
  },
  "type": "virtual_host",
  "event": "delete"
}
```

<a id="webhook-events-virtual-host-monitor-updated"></a>

### Virtual Host Monitor Updated

Triggered when the active monitoring for each virtual host incoming address detects a change in the DNS, SSL, APX Hit, or resolving statuses.

Included for convenience is a 'changes' field that will provide the old and new values for any fields that have changed.

**Note:** this event is NOT automatically triggered by configuration changes made to a virtual host using the dashboard or API, though they may indirectly result in this event being triggered if statuses change. To be notified of configuration changes to the virtual host, please use the [Virtual Host Updated event](#webhook-events-virtual-host-updated) instead.

Example event payload:

```json
{
  "idempotent_key": "apx-whl-1234567893",
  "data": {
    "url": "acustomdomain.com",
    "status": "DNS_INCORRECT",
    "apx_hit": false,
    "changes": {
      "dns_resolution": {
        "new": "34.224.149.186, 3.18.255.247",
        "old": "4.16.255.147, 35.223.139.196"
      }
    },
    "has_ssl": false,
    "dns_details": {
      "values": [
        "34.224.149.186",
        "3.18.255.247"
      ],
      "wrong_ips": [
        "34.224.149.186",
        "3.18.255.247"
      ],
      "contains_cluster_ip": false
    },
    "is_resolving": false,
    "dns_pointed_at": "34.224.149.186, 3.18.255.247",
    "status_message": "DNS incorrect",
    "ssl_active_from": "2024-10-17T14:21:20",
    "virtual_host_id": 1186546,
    "ssl_active_until": "2025-11-17T14:20:20",
    "last_monitored_unix": 1746479579
  },
  "type": "virtual_host_monitor",
  "event": "update"
}
```

**Multiple IP addresses in DNS values:**  
In some cases, monitors will find multiple IP addresses in the DNS records for a domain.

This occurs when there are either multiple records with different IP addresses, for the same host, or in some cases when a CNAME record is used to indirectly point the custom domain through another domain/subdomain.

Multiple IP addresses are not always an issue, particularly when combining Approximated Cloud with Self Hosted instances, but it can be an indication of improperly configured DNS records for a domain.
