mirror of https://github.com/h44z/wg-portal.git
				
				
				
			
		
			
				
	
	
		
			285 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Markdown
		
	
	
	
			
		
		
	
	
			285 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Markdown
		
	
	
	
 | 
						|
Webhooks allow WireGuard Portal to notify external services about events such as user creation, device changes, or configuration updates. This enables integration with other systems and automation workflows.
 | 
						|
 | 
						|
When webhooks are configured and a specified event occurs, WireGuard Portal sends an HTTP **POST** request to the configured webhook URL. 
 | 
						|
The payload contains event-specific data in JSON format.
 | 
						|
 | 
						|
## Configuration
 | 
						|
 | 
						|
All available configuration options for webhooks can be found in the [configuration overview](../configuration/overview.md#webhook).
 | 
						|
 | 
						|
A basic webhook configuration looks like this:
 | 
						|
 | 
						|
```yaml
 | 
						|
webhook:
 | 
						|
  url: https://your-service.example.com/webhook
 | 
						|
```
 | 
						|
 | 
						|
### Security
 | 
						|
 | 
						|
Webhooks can be secured by using a shared secret. This secret is included in the `Authorization` header of the webhook request, allowing your service to verify the authenticity of the request.
 | 
						|
You can set the shared secret in the webhook configuration:
 | 
						|
 | 
						|
```yaml
 | 
						|
webhook:
 | 
						|
  url: https://your-service.example.com/webhook
 | 
						|
  secret: "Basic dXNlcm5hbWU6cGFzc3dvcmQ="
 | 
						|
```
 | 
						|
 | 
						|
You should also make sure that your webhook endpoint is secured with HTTPS to prevent eavesdropping and tampering.
 | 
						|
 | 
						|
## Available Events
 | 
						|
 | 
						|
WireGuard Portal supports various events that can trigger webhooks. The following events are available:
 | 
						|
 | 
						|
- `create`: Triggered when a new entity is created.
 | 
						|
- `update`: Triggered when an existing entity is updated.
 | 
						|
- `delete`: Triggered when an entity is deleted.
 | 
						|
- `connect`: Triggered when a user connects to the VPN.
 | 
						|
- `disconnect`: Triggered when a user disconnects from the VPN.
 | 
						|
 | 
						|
The following entity models are supported for webhook events:
 | 
						|
 | 
						|
- `user`: WireGuard Portal users support creation, update, or deletion events.
 | 
						|
- `peer`: Peers support creation, update, or deletion events. Via the `peer_metric` entity, you can also receive connection status updates.
 | 
						|
- `peer_metric`: Peer metrics support connection status updates, such as when a peer connects or disconnects.
 | 
						|
- `interface`: WireGuard interfaces support creation, update, or deletion events.
 | 
						|
 | 
						|
## Payload Structure
 | 
						|
 | 
						|
All webhook events send a JSON payload containing relevant data. The structure of the payload depends on the event type and entity involved.
 | 
						|
A common shell structure for webhook payloads is as follows:
 | 
						|
 | 
						|
```json
 | 
						|
{
 | 
						|
  "event": "create", // The event type, e.g. "create", "update", "delete", "connect", "disconnect"
 | 
						|
  "entity": "user",  // The entity type, e.g. "user", "peer", "peer_metric", "interface"
 | 
						|
  "identifier": "the-user-identifier", // Unique identifier of the entity, e.g. user ID or peer ID
 | 
						|
  "payload": {
 | 
						|
    // The payload of the event, e.g. a Peer model.
 | 
						|
    // Detailed model descriptions are provided below.
 | 
						|
  }
 | 
						|
}
 | 
						|
```
 | 
						|
 | 
						|
### Payload Models
 | 
						|
 | 
						|
All payload models are encoded as JSON objects. Fields with empty values might be omitted in the payload.
 | 
						|
 | 
						|
#### User Payload (entity: `user`)
 | 
						|
 | 
						|
| JSON Field     | Type        | Description                       |
 | 
						|
|----------------|-------------|-----------------------------------|
 | 
						|
| CreatedBy      | string      | Creator identifier                |
 | 
						|
| UpdatedBy      | string      | Last updater identifier           |
 | 
						|
| CreatedAt      | time.Time   | Time of creation                  |
 | 
						|
| UpdatedAt      | time.Time   | Time of last update               |
 | 
						|
| Identifier     | string      | Unique user identifier            |
 | 
						|
| Email          | string      | User email                        |
 | 
						|
| Source         | string      | Authentication source             |
 | 
						|
| ProviderName   | string      | Name of auth provider             |
 | 
						|
| IsAdmin        | bool        | Whether user has admin privileges |
 | 
						|
| Firstname      | string      | User's first name (optional)      |
 | 
						|
| Lastname       | string      | User's last name (optional)       |
 | 
						|
| Phone          | string      | Contact phone number (optional)   |
 | 
						|
| Department     | string      | User's department (optional)      |
 | 
						|
| Notes          | string      | Additional notes (optional)       |
 | 
						|
| Disabled       | *time.Time  | When user was disabled            |
 | 
						|
| DisabledReason | string      | Reason for deactivation           |
 | 
						|
| Locked         | *time.Time  | When user account was locked      |
 | 
						|
| LockedReason   | string      | Reason for being locked           |
 | 
						|
 | 
						|
 | 
						|
#### Peer Payload (entity: `peer`)
 | 
						|
 | 
						|
| JSON Field           | Type       | Description                            |
 | 
						|
|----------------------|------------|----------------------------------------|
 | 
						|
| CreatedBy            | string     | Creator identifier                     |
 | 
						|
| UpdatedBy            | string     | Last updater identifier                |
 | 
						|
| CreatedAt            | time.Time  | Creation timestamp                     |
 | 
						|
| UpdatedAt            | time.Time  | Last update timestamp                  |
 | 
						|
| Endpoint             | string     | Peer endpoint address                  |
 | 
						|
| EndpointPublicKey    | string     | Public key of peer endpoint            |
 | 
						|
| AllowedIPsStr        | string     | Allowed IPs                            |
 | 
						|
| ExtraAllowedIPsStr   | string     | Extra allowed IPs                      |
 | 
						|
| PresharedKey         | string     | Pre-shared key for encryption          |
 | 
						|
| PersistentKeepalive  | int        | Keepalive interval in seconds          |
 | 
						|
| DisplayName          | string     | Display name of the peer               |
 | 
						|
| Identifier           | string     | Unique identifier                      |
 | 
						|
| UserIdentifier       | string     | Associated user ID (optional)          |
 | 
						|
| InterfaceIdentifier  | string     | Interface this peer is attached to     |
 | 
						|
| Disabled             | *time.Time | When the peer was disabled             |
 | 
						|
| DisabledReason       | string     | Reason for being disabled              |
 | 
						|
| ExpiresAt            | *time.Time | Expiration date                        |
 | 
						|
| Notes                | string     | Notes for this peer                    |
 | 
						|
| AutomaticallyCreated | bool       | Whether peer was auto-generated        |
 | 
						|
| PrivateKey           | string     | Peer private key                       |
 | 
						|
| PublicKey            | string     | Peer public key                        |
 | 
						|
| InterfaceType        | string     | Type of the peer interface             |
 | 
						|
| Addresses            | []string   | IP addresses                           |
 | 
						|
| CheckAliveAddress    | string     | Address used for alive checks          |
 | 
						|
| DnsStr               | string     | DNS servers                            |
 | 
						|
| DnsSearchStr         | string     | DNS search domains                     |
 | 
						|
| Mtu                  | int        | MTU (Maximum Transmission Unit)        |
 | 
						|
| FirewallMark         | uint32     | Firewall mark (optional)               |
 | 
						|
| RoutingTable         | string     | Custom routing table (optional)        |
 | 
						|
| PreUp                | string     | Command before bringing up interface   |
 | 
						|
| PostUp               | string     | Command after bringing up interface    |
 | 
						|
| PreDown              | string     | Command before bringing down interface |
 | 
						|
| PostDown             | string     | Command after bringing down interface  |
 | 
						|
 | 
						|
 | 
						|
#### Interface Payload (entity: `interface`)
 | 
						|
 | 
						|
| JSON Field                 | Type       | Description                            |
 | 
						|
|----------------------------|------------|----------------------------------------|
 | 
						|
| CreatedBy                  | string     | Creator identifier                     |
 | 
						|
| UpdatedBy                  | string     | Last updater identifier                |
 | 
						|
| CreatedAt                  | time.Time  | Creation timestamp                     |
 | 
						|
| UpdatedAt                  | time.Time  | Last update timestamp                  |
 | 
						|
| Identifier                 | string     | Unique identifier                      |
 | 
						|
| PrivateKey                 | string     | Private key for the interface          |
 | 
						|
| PublicKey                  | string     | Public key for the interface           |
 | 
						|
| ListenPort                 | int        | Listening port                         |
 | 
						|
| Addresses                  | []string   | IP addresses                           |
 | 
						|
| DnsStr                     | string     | DNS servers                            |
 | 
						|
| DnsSearchStr               | string     | DNS search domains                     |
 | 
						|
| Mtu                        | int        | MTU (Maximum Transmission Unit)        |
 | 
						|
| FirewallMark               | uint32     | Firewall mark                          |
 | 
						|
| RoutingTable               | string     | Custom routing table                   |
 | 
						|
| PreUp                      | string     | Command before bringing up interface   |
 | 
						|
| PostUp                     | string     | Command after bringing up interface    |
 | 
						|
| PreDown                    | string     | Command before bringing down interface |
 | 
						|
| PostDown                   | string     | Command after bringing down interface  |
 | 
						|
| SaveConfig                 | bool       | Whether to save config to file         |
 | 
						|
| DisplayName                | string     | Human-readable name                    |
 | 
						|
| Type                       | string     | Type of interface                      |
 | 
						|
| DriverType                 | string     | Driver used                            |
 | 
						|
| Disabled                   | *time.Time | When the interface was disabled        |
 | 
						|
| DisabledReason             | string     | Reason for being disabled              |
 | 
						|
| PeerDefNetworkStr          | string     | Default peer network configuration     |
 | 
						|
| PeerDefDnsStr              | string     | Default peer DNS servers               |
 | 
						|
| PeerDefDnsSearchStr        | string     | Default peer DNS search domains        |
 | 
						|
| PeerDefEndpoint            | string     | Default peer endpoint                  |
 | 
						|
| PeerDefAllowedIPsStr       | string     | Default peer allowed IPs               |
 | 
						|
| PeerDefMtu                 | int        | Default peer MTU                       |
 | 
						|
| PeerDefPersistentKeepalive | int        | Default keepalive value                |
 | 
						|
| PeerDefFirewallMark        | uint32     | Default firewall mark for peers        |
 | 
						|
| PeerDefRoutingTable        | string     | Default routing table for peers        |
 | 
						|
| PeerDefPreUp               | string     | Default peer pre-up command            |
 | 
						|
| PeerDefPostUp              | string     | Default peer post-up command           |
 | 
						|
| PeerDefPreDown             | string     | Default peer pre-down command          |
 | 
						|
| PeerDefPostDown            | string     | Default peer post-down command         |
 | 
						|
 | 
						|
 | 
						|
#### Peer Metrics Payload (entity: `peer_metric`)
 | 
						|
 | 
						|
| JSON Field | Type       | Description                |
 | 
						|
|------------|------------|----------------------------|
 | 
						|
| Status     | PeerStatus | Current status of the peer |
 | 
						|
| Peer       | Peer       | Peer  data                 |
 | 
						|
 | 
						|
`PeerStatus` sub-structure:
 | 
						|
 | 
						|
| JSON Field       | Type       | Description                  |
 | 
						|
|------------------|------------|------------------------------|
 | 
						|
| UpdatedAt        | time.Time  | Time of last status update   |
 | 
						|
| IsConnected      | bool       | Is peer currently connected  |
 | 
						|
| IsPingable       | bool       | Can peer be pinged           |
 | 
						|
| LastPing         | *time.Time | Time of last successful ping |
 | 
						|
| BytesReceived    | uint64     | Bytes received from peer     |
 | 
						|
| BytesTransmitted | uint64     | Bytes sent to peer           |
 | 
						|
| Endpoint         | string     | Last known endpoint          |
 | 
						|
| LastHandshake    | *time.Time | Last successful handshake    |
 | 
						|
| LastSessionStart | *time.Time | Time the last session began  |
 | 
						|
 | 
						|
 | 
						|
### Example Payloads
 | 
						|
 | 
						|
The following payload is an example of a webhook event when a peer connects to the VPN:
 | 
						|
 | 
						|
```json
 | 
						|
{
 | 
						|
  "event": "connect",
 | 
						|
  "entity": "peer_metric",
 | 
						|
  "identifier": "Fb5TaziAs1WrPBjC/MFbWsIelVXvi0hDKZ3YQM9wmU8=",
 | 
						|
  "payload": {
 | 
						|
    "Status": {
 | 
						|
      "UpdatedAt": "2025-06-27T22:20:08.734900034+02:00",
 | 
						|
      "IsConnected": true,
 | 
						|
      "IsPingable": false,
 | 
						|
      "BytesReceived": 212,
 | 
						|
      "BytesTransmitted": 2884,
 | 
						|
      "Endpoint": "10.55.66.77:58756",
 | 
						|
      "LastHandshake": "2025-06-27T22:19:46.580842776+02:00",
 | 
						|
      "LastSessionStart": "2025-06-27T22:19:46.580842776+02:00"
 | 
						|
    },
 | 
						|
    "Peer": {
 | 
						|
      "CreatedBy": "admin@wgportal.local",
 | 
						|
      "UpdatedBy": "admin@wgportal.local",
 | 
						|
      "CreatedAt": "2025-06-26T21:43:49.251839574+02:00",
 | 
						|
      "UpdatedAt": "2025-06-27T22:18:39.67763985+02:00",
 | 
						|
      "Endpoint": "10.55.66.1:51820",
 | 
						|
      "EndpointPublicKey": "eiVibpi3C2PUPcx2kwA5s09OgHx7AEaKMd33k0LQ5mM=",
 | 
						|
      "AllowedIPsStr": "10.11.12.0/24,fdfd:d3ad:c0de:1234::/64",
 | 
						|
      "ExtraAllowedIPsStr": "",
 | 
						|
      "PresharedKey": "p9DDeLUSLOdQcjS8ZsBAiqUzwDIUvTyzavRZFuzhvyE=",
 | 
						|
      "PersistentKeepalive": 16,
 | 
						|
      "DisplayName": "Peer Fb5TaziA",
 | 
						|
      "Identifier": "Fb5TaziAs1WrPBjC/MFbWsIelVXvi0hDKZ3YQM9wmU8=",
 | 
						|
      "UserIdentifier": "admin@wgportal.local",
 | 
						|
      "InterfaceIdentifier": "wgTesting",
 | 
						|
      "AutomaticallyCreated": false,
 | 
						|
      "PrivateKey": "QBFNBe+7J49ergH0ze2TGUJMFrL/2bOL50Z2cgluYW8=",
 | 
						|
      "PublicKey": "Fb5TaziAs1WrPBjC/MFbWsIelVXvi0hDKZ3YQM9wmU8=",
 | 
						|
      "InterfaceType": "client",
 | 
						|
      "Addresses": [
 | 
						|
        "10.11.12.10/32",
 | 
						|
        "fdfd:d3ad:c0de:1234::a/128"
 | 
						|
      ],
 | 
						|
      "CheckAliveAddress": "",
 | 
						|
      "DnsStr": "",
 | 
						|
      "DnsSearchStr": "",
 | 
						|
      "Mtu": 1420
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
```
 | 
						|
 | 
						|
Here is another example of a webhook event when a peer is updated:
 | 
						|
 | 
						|
```json
 | 
						|
{
 | 
						|
  "event": "update",
 | 
						|
  "entity": "peer",
 | 
						|
  "identifier": "Fb5TaziAs1WrPBjC/MFbWsIelVXvi0hDKZ3YQM9wmU8=",
 | 
						|
  "payload": {
 | 
						|
    "CreatedBy": "admin@wgportal.local",
 | 
						|
    "UpdatedBy": "admin@wgportal.local",
 | 
						|
    "CreatedAt": "2025-06-26T21:43:49.251839574+02:00",
 | 
						|
    "UpdatedAt": "2025-06-27T22:18:39.67763985+02:00",
 | 
						|
    "Endpoint": "10.55.66.1:51820",
 | 
						|
    "EndpointPublicKey": "eiVibpi3C2PUPcx2kwA5s09OgHx7AEaKMd33k0LQ5mM=",
 | 
						|
    "AllowedIPsStr": "10.11.12.0/24,fdfd:d3ad:c0de:1234::/64",
 | 
						|
    "ExtraAllowedIPsStr": "",
 | 
						|
    "PresharedKey": "p9DDeLUSLOdQcjS8ZsBAiqUzwDIUvTyzavRZFuzhvyE=",
 | 
						|
    "PersistentKeepalive": 16,
 | 
						|
    "DisplayName": "Peer Fb5TaziA",
 | 
						|
    "Identifier": "Fb5TaziAs1WrPBjC/MFbWsIelVXvi0hDKZ3YQM9wmU8=",
 | 
						|
    "UserIdentifier": "admin@wgportal.local",
 | 
						|
    "InterfaceIdentifier": "wgTesting",
 | 
						|
    "AutomaticallyCreated": false,
 | 
						|
    "PrivateKey": "QBFNBe+7J49ergH0ze2TGUJMFrL/2bOL50Z2cgluYW8=",
 | 
						|
    "PublicKey": "Fb5TaziAs1WrPBjC/MFbWsIelVXvi0hDKZ3YQM9wmU8=",
 | 
						|
    "InterfaceType": "client",
 | 
						|
    "Addresses": [
 | 
						|
      "10.11.12.10/32",
 | 
						|
      "fdfd:d3ad:c0de:1234::a/128"
 | 
						|
    ],
 | 
						|
    "CheckAliveAddress": "",
 | 
						|
    "DnsStr": "",
 | 
						|
    "DnsSearchStr": "",
 | 
						|
    "Mtu": 1420
 | 
						|
  }
 | 
						|
}
 | 
						|
``` |