Webhooks
Webhooks are POST requests sent by AdaptGroup to your server when subscription events occur. Configure your webhook URL and secret in the dashboard.
Request format
Each webhook request has the following structure:
{
"event": "subs.created",
"timestamp": "2026-05-04T12:00:00.000Z",
"data": { ... }
}
| Field | Type | Description |
|---|---|---|
event | string | Event type |
timestamp | string | UTC timestamp in ISO 8601 format |
data | object | Event payload, varies by event type |
Authentication
Each webhook request includes an X-Webhook-Signature header — HMAC-SHA256 of the request body using your secret.
const crypto = require('crypto');
function verifySignature(body, secret, signature) {
const expected = crypto
.createHmac('sha256', secret)
.update(body)
.digest('hex');
return expected === signature;
}
IP address
All webhooks are sent from IP address 139.60.162.7. Add it to your server's allowlist to ensure webhook delivery.
Retry policy
If your server does not respond with 200 or 201, AdaptGroup will retry the webhook:
| Attempt | Delay |
|---|---|
| 1 | Immediately |
| 2 | 1 minute |
| 3 | 2 minutes |
| 4 | 5 minutes |
| 5 | 10 minutes |
| 6 | 15 minutes |
| 7 | 30 minutes |
| 8 | 1 hour |
| 9 | 2 hours |
| 10 | 2 hours |
If the webhook is not delivered after all attempts (~6 hours total), it is discarded.
Events
subs.created
Sent when a new subscription is created.
| Field | Type | Description |
|---|---|---|
subscription_uuid | string | Subscription UUID |
subscription_url | string | VPN configuration URL |
plan_uuid | string | Plan UUID |
external_user_id | string | null | Your system's user ID |
devices | integer | Maximum number of devices |
days | integer | Subscription duration in days |
traffic_limit_bytes | integer | null | Traffic limit in bytes, null if unlimited |
end_date | string | Subscription end date (ISO 8601) |
{
"event": "subs.created",
"timestamp": "2026-05-04T12:00:00.000Z",
"data": {
"subscription_uuid": "770fa622-a4bd-63f6-c938-668877662222",
"subscription_url": "https://network-api.adaptgroup.app/sub/770fa622-a4bd-63f6-c938-668877662222",
"plan_uuid": "550e8400-e29b-41d4-a716-446655440000",
"external_user_id": "user_123",
"devices": 3,
"days": 30,
"traffic_limit_bytes": null,
"end_date": "2026-06-04T12:00:00"
}
}
subs.renewed
Sent when a subscription is renewed.
| Field | Type | Description |
|---|---|---|
subscription_uuid | string | Subscription UUID |
subscription_url | string | VPN configuration URL |
external_user_id | string | null | Your system's user ID |
days | integer | Added days |
traffic_limit_bytes | integer | null | Added traffic in bytes, null if plan has no limit |
end_date | string | New end date (ISO 8601) |
{
"event": "subs.renewed",
"timestamp": "2026-05-04T12:00:00.000Z",
"data": {
"subscription_uuid": "770fa622-a4bd-63f6-c938-668877662222",
"subscription_url": "https://network-api.adaptgroup.app/sub/770fa622-a4bd-63f6-c938-668877662222",
"external_user_id": "user_123",
"days": 30,
"traffic_limit_bytes": null,
"end_date": "2026-07-04T12:00:00"
}
}
subs.upgraded
Sent when a subscription plan is upgraded.
| Field | Type | Description |
|---|---|---|
subscription_uuid | string | Subscription UUID |
subscription_url | string | VPN configuration URL |
external_user_id | string | null | Your system's user ID |
old_plan_uuid | string | Previous plan UUID |
new_plan_uuid | string | New plan UUID |
devices | integer | New maximum number of devices |
additional_bytes | integer | Additional traffic added in bytes |
{
"event": "subs.upgraded",
"timestamp": "2026-05-04T12:00:00.000Z",
"data": {
"subscription_uuid": "770fa622-a4bd-63f6-c938-668877662222",
"subscription_url": "https://network-api.adaptgroup.app/sub/770fa622-a4bd-63f6-c938-668877662222",
"external_user_id": "user_123",
"old_plan_uuid": "550e8400-e29b-41d4-a716-446655440000",
"new_plan_uuid": "661f9511-f3ac-52e5-b827-557766551111",
"devices": 5,
"additional_bytes": 53687091200
}
}
subs.traffic_purchased
Sent when additional traffic is purchased for a subscription.
| Field | Type | Description |
|---|---|---|
subscription_uuid | string | Subscription UUID |
subscription_url | string | VPN configuration URL |
external_user_id | string | null | Your system's user ID |
gb_amount | integer | Purchased amount in GB |
additional_bytes | integer | Purchased amount in bytes |
{
"event": "subs.traffic_purchased",
"timestamp": "2026-05-04T12:00:00.000Z",
"data": {
"subscription_uuid": "770fa622-a4bd-63f6-c938-668877662222",
"subscription_url": "https://network-api.adaptgroup.app/sub/770fa622-a4bd-63f6-c938-668877662222",
"external_user_id": "user_123",
"gb_amount": 10,
"additional_bytes": 10737418240
}
}
subs.expires_in_72_hours
Sent when a subscription expires in 72 hours.
| Field | Type | Description |
|---|---|---|
subscription_uuid | string | Subscription UUID |
subscription_url | string | VPN configuration URL |
external_user_id | string | null | Your system's user ID |
end_date | string | Subscription end date (ISO 8601) |
{
"event": "subs.expires_in_72_hours",
"timestamp": "2026-05-04T12:00:00.000Z",
"data": {
"subscription_uuid": "770fa622-a4bd-63f6-c938-668877662222",
"subscription_url": "https://network-api.adaptgroup.app/sub/770fa622-a4bd-63f6-c938-668877662222",
"external_user_id": "user_123",
"end_date": "2026-05-07T12:00:00"
}
}
subs.expires_in_48_hours
Sent when a subscription expires in 48 hours.
{
"event": "subs.expires_in_48_hours",
"timestamp": "2026-05-04T12:00:00.000Z",
"data": {
"subscription_uuid": "770fa622-a4bd-63f6-c938-668877662222",
"subscription_url": "https://network-api.adaptgroup.app/sub/770fa622-a4bd-63f6-c938-668877662222",
"external_user_id": "user_123",
"end_date": "2026-05-06T12:00:00"
}
}
subs.expires_in_24_hours
Sent when a subscription expires in 24 hours.
{
"event": "subs.expires_in_24_hours",
"timestamp": "2026-05-04T12:00:00.000Z",
"data": {
"subscription_uuid": "770fa622-a4bd-63f6-c938-668877662222",
"subscription_url": "https://network-api.adaptgroup.app/sub/770fa622-a4bd-63f6-c938-668877662222",
"external_user_id": "user_123",
"end_date": "2026-05-05T12:00:00"
}
}
subs.expired
Sent when a subscription expires.
{
"event": "subs.expired",
"timestamp": "2026-05-04T12:00:00.000Z",
"data": {
"subscription_uuid": "770fa622-a4bd-63f6-c938-668877662222",
"subscription_url": "https://network-api.adaptgroup.app/sub/770fa622-a4bd-63f6-c938-668877662222",
"external_user_id": "user_123",
"end_date": "2026-05-04T12:00:00"
}
}
subs.expired_24_hours_ago
Sent 24 hours after a subscription has expired.
{
"event": "subs.expired_24_hours_ago",
"timestamp": "2026-05-05T12:00:00.000Z",
"data": {
"subscription_uuid": "770fa622-a4bd-63f6-c938-668877662222",
"subscription_url": "https://network-api.adaptgroup.app/sub/770fa622-a4bd-63f6-c938-668877662222",
"external_user_id": "user_123",
"end_date": "2026-05-04T12:00:00"
}
}
subs.traffic_threshold_reached
Sent when a subscription's traffic usage reaches the configured threshold.
| Field | Type | Description |
|---|---|---|
subscription_uuid | string | Subscription UUID |
subscription_url | string | VPN configuration URL |
external_user_id | string | null | Your system's user ID |
used_traffic_bytes | integer | Traffic used in bytes |
traffic_limit_bytes | integer | Total traffic limit in bytes |
{
"event": "subs.traffic_threshold_reached",
"timestamp": "2026-05-04T12:00:00.000Z",
"data": {
"subscription_uuid": "770fa622-a4bd-63f6-c938-668877662222",
"subscription_url": "https://network-api.adaptgroup.app/sub/770fa622-a4bd-63f6-c938-668877662222",
"external_user_id": "user_123",
"used_traffic_bytes": 96636764160,
"traffic_limit_bytes": 107374182400
}
}