For the complete documentation index, see llms.txt. This page is also available as Markdown.

πŸͺHTTP Webhooks

HTTP webhooks allow you to receive real-time event notifications from AntVPN via standard HTTP POST requests to your own server

How It Works

When an event occurs (e.g. a player is blocked), AntVPN sends an HTTP POST request to your configured webhook URL with:

  • A JSON body containing the event message

  • An X-AntiVPN-Signature header (if a webhook secret is configured)

  • Content-Type: application/json

  • User-Agent: AntiVPN-Webhook/1.0


Webhook Secret & Signature Verification

When you configure a webhook secret, every outgoing request includes an X-AntiVPN-Signature header. This header contains an HMAC-SHA256 signature of the raw request body, computed using your secret as the key.

Header Format

X-AntiVPN-Signature: sha256=<hex-encoded HMAC-SHA256>

If no secret is configured, the X-AntiVPN-Signature header is not sent.

How the Signature Is Computed

  1. The raw JSON request body is used as the message.

  2. An HMAC-SHA256 hash is computed using your webhook secret as the key.

  3. The resulting hash is hex-encoded and prefixed with sha256=.


Verifying the Signature on Your Server

To verify that an incoming webhook request is authentic:

  1. Read the raw request body (do not parse it first).

  2. Compute the HMAC-SHA256 of the raw body using your webhook secret.

  3. Compare the computed signature with the value in X-AntiVPN-Signature.

  4. Use a constant-time comparison to prevent timing attacks.

Node.js Example

Python Example

Go Example

Java Example


Request Headers

Every HTTP webhook request includes the following headers:

Header
Description

Content-Type

Always application/json.

User-Agent

Always AntiVPN-Webhook/1.0.

X-AntiVPN-Signature

HMAC-SHA256 signature of the body (only present if a secret is configured).


Webhook Events

HTTP webhooks can subscribe to the following events:

blocked

Fired when a player connection is blocked by AntVPN.

Available placeholders:

Placeholder
Description

{username}

The player's username.

{userUniqueId}

The player's unique identifier.

{ip}

The player's IP address.

{reason}

The reason the connection was blocked.

{country}

The country ISO code of the IP.

{asn}

The ASN number associated with the IP.

{blocked}

Whether the IP was blocked (true/false).

{riskScore}

The risk score assigned to the IP.

{riskLevel}

The risk level category.

{provider}

The network provider name.

shielded

Fired when a new attack is detected.

Available placeholders:

Placeholder
Description

{attack_rps}

Current requests per second.

{attack_rpm}

Average requests per minute (1-minute window).

{attack_rpm_5min}

Average requests per minute (5-minute window).

{attack_started}

Unix timestamp when the attack started.

{attack_duration}

Duration of the attack in seconds (initially 0).

unshielded

Fired when an attack has ended.

Available placeholders:

Placeholder
Description

{attack_duration}

Total attack duration in seconds.

{attack_started}

Unix timestamp when the attack started.

{attack_ended}

Unix timestamp when the attack ended.

{attack_duration_formatted}

Human-readable attack duration (e.g. 1m30s).


Timeouts & Retries

  • Requests have a 10-second timeout.

  • Failed requests are retried up to 3 times.

  • If your server responds with 429 Too Many Requests, AntVPN will respect the Retry-After header (or wait 2 seconds by default) before retrying.


Best Practices

  • Always verify the signature before processing webhook data.

  • Use constant-time comparison (e.g. crypto.timingSafeEqual, hmac.compare_digest, hmac.Equal) to prevent timing attacks.

  • Read the raw body before parsing JSON β€” signature verification must be done on the exact bytes sent.

  • Respond quickly with a 2xx status code. Perform any heavy processing asynchronously after responding.

  • Store your webhook secret securely (e.g. environment variables, secret managers). Do not hard-code it in your source.

  • Return 401 if signature verification fails, so issues are easy to diagnose in logs.

Last updated