Wgua.eu API (0.1.0)

Download OpenAPI specification:

REST API for the wgua.eu WireGuard VPN subscription platform.

STB (set-top box) clients use this API to provision customers and manage subscriptions. The payment form endpoints (/pay/*) are browser-facing and are not called by the STB directly.

Authentication

All endpoints except /pay/* require an X-API-Key header. Keys are issued per operator through the admin portal. A key is scoped to a single operator — customers created with a key belong to that operator and are only visible through the same key.

Rate limiting

20 requests per second per IP address with a burst allowance of 40.

Customer lifecycle

A customer record is created once per device using POST /customers and persists indefinitely. When a subscription expires the STB must call POST /customers/{customerId}/payment to prompt the user to renew. Never create a new customer to replace an expired one. Creating a new customer allocates a new IP address and generates new WireGuard keys, permanently breaking the user's VPN identity.

Customers

Customer provisioning and management.

List customers

Returns all customers belonging to the authenticated operator.

Returns 404 when the operator has no customers yet (not an auth error).

Authorizations:
ApiKeyAuth

Responses

Response samples

Content type
application/json
[
  • {
    }
]

Create customer

Provisions a new WireGuard peer. Call this endpoint exactly once per device, at first boot, after confirming that GET /customers returns no existing customers.

The server:

  • Generates a WireGuard key pair.
  • Allocates a random free IP address from the 100.80.0.0/16 pool.
  • Sets the subscription to expire after a server-configured trial period.

Do not call this endpoint again when a subscription expires. Use POST /customers/{customerId}/payment to renew the existing customer. Creating a second customer permanently discards the previous IP and keys.

Store customer_id and private_key on the device immediately. The private_key is also retrievable later via GET /customers/{customerId}, which makes credential recovery possible after data loss.

Authorizations:
ApiKeyAuth

Responses

Response samples

Content type
application/json
{
  • "customer_id": "01ARZ3NDEKTSV4RRFFQ69G5FAV",
  • "endpoint": "01ARZ3NDEKTSV4RRFFQ69G5FAV.wgua.eu",
  • "ip_address": "100.80.4.17/32",
  • "peer_public_key": "base64encodedServerPublicKey=",
  • "private_key": "base64encodedPrivateKey=",
  • "public_key": "base64encodedPublicKey=",
  • "created": "2026-03-27T10:00:00Z",
  • "expires": "2026-04-10T10:00:00Z",
  • "active": true
}

Get customer

Returns the current state of a customer, including subscription status and WireGuard credentials.

Poll this endpoint to detect subscription changes (e.g. after presenting a payment link). Use active to determine whether VPN access is currently granted. Use expires to decide when to proactively offer renewal before the subscription lapses.

This endpoint returns the private_key, which allows full WireGuard configuration to be restored from just the customer_id (see POST /customers/recover for the recovery flow).

Returns 404 if the customer does not exist or belongs to a different operator.

Authorizations:
ApiKeyAuth
path Parameters
customerId
required
string
Example: 01ARZ3NDEKTSV4RRFFQ69G5FAV

Unique customer identifier (ULID).

Responses

Response samples

Content type
application/json
{
  • "customer_id": "01ARZ3NDEKTSV4RRFFQ69G5FAV",
  • "endpoint": "01ARZ3NDEKTSV4RRFFQ69G5FAV.wgua.eu",
  • "ip_address": "100.80.4.17",
  • "peer_public_key": "base64encodedServerPublicKey=",
  • "private_key": "base64encodedPrivateKey=",
  • "public_key": "base64encodedPublicKey=",
  • "created": "2026-03-01T12:00:00Z",
  • "expires": "2026-04-01T12:00:00Z",
  • "active": true
}

Delete customer

Permanently removes a customer. All stored fields (keys, IP assignment, subscription dates) are cleared and the IP address is returned to the allocation pool. This operation is irreversible through the API.

Use this only to fully deprovision a device. Do not delete and recreate a customer to renew a subscription — use POST /customers/{customerId}/payment instead.

Returns 404 if the customer does not exist or belongs to a different operator.

Authorizations:
ApiKeyAuth
path Parameters
customerId
required
string
Example: 01ARZ3NDEKTSV4RRFFQ69G5FAV

Unique customer identifier (ULID).

Responses

Response samples

Content type
application/json
{
  • "error": "Unauthorized"
}

Get recovery code

Returns the recovery code for a customer. The code is generated on the first call and persists indefinitely — subsequent calls return the same code.

Store the recovery code alongside the customer credentials. If the device loses its local database, the code can be used with POST /customers/recover to look up the customer_id, after which GET /customers/{customerId} returns the full credentials including private_key.

The code uses an alphabet that excludes visually ambiguous characters (I, O, S, Z) to reduce transcription errors when users enter codes manually.

Returns 404 if the customer does not exist or belongs to a different operator.

Authorizations:
ApiKeyAuth
path Parameters
customerId
required
string
Example: 01ARZ3NDEKTSV4RRFFQ69G5FAV

Unique customer identifier (ULID).

Responses

Response samples

Content type
application/json
{
  • "recovery_code": "A1-2B3C"
}

Recover customer ID

Looks up a customer_id by its recovery code. Use this when an STB has lost its local database and needs to recover its VPN credentials.

Recovery flow:

  1. Call this endpoint with the recovery code to obtain the customer_id.
  2. Call GET /customers/{customerId} to retrieve full credentials including private_key.
  3. Reconfigure the WireGuard tunnel with the recovered credentials.

The recovery code must belong to a customer owned by the authenticating operator. Returns 404 if no matching customer is found.

Authorizations:
ApiKeyAuth
Request Body schema: application/json
required
recovery_code
required
string

The recovery code previously obtained from GET /customers/{customerId}/recovery_code.

Responses

Request samples

Content type
application/json
{
  • "recovery_code": "A1-2B3C"
}

Response samples

Content type
application/json
{
  • "customer_id": "01ARZ3NDEKTSV4RRFFQ69G5FAV"
}

Payments

Subscription payment flow.

Create payment link

Creates a hosted payment form URL for the customer to renew their subscription. The link is valid for 24 hours.

The STB presents the url to the end user as a link or QR code. The user opens it in a browser, selects a subscription plan, and is redirected to the payment gateway. The STB is not involved further in the payment flow.

After a successful payment:

  • The customer's expires is extended by the purchased plan's duration.
  • Speed limits are updated to the plan's values.
  • Changes are applied to the WireGuard server within 10 seconds.

The STB can detect that renewal completed by polling GET /customers/{customerId} and checking that active is true or that expires has advanced.

Multiple payment links can exist simultaneously for the same customer. Any one of them completing a payment will extend the subscription.

Call this endpoint when active is false or expires is approaching. Do not create a new customer.

Authorizations:
ApiKeyAuth
path Parameters
customerId
required
string
Example: 01ARZ3NDEKTSV4RRFFQ69G5FAV

Unique customer identifier (ULID).

Responses

Response samples

Content type
application/json
{}

Show payment form

Browser-facing endpoint. Returns an HTML page listing available subscription plans with prices in UAH, USD, and EUR.

Not called by the STB — the URL is obtained from POST /customers/{customerId}/payment and opened by the end user.

If the payment link has expired the page displays an expiry notice rather than the plan selection form; both cases return HTTP 200.

path Parameters
paymentReference
required
string
Example: 01BX5ZZKBKACTAV9WEVGEMMVS0

Unique payment reference (ULID) returned by POST /customers/{customerId}/payment.

Responses

Submit plan selection

Browser-facing endpoint. Accepts the plan chosen by the user, creates the payment transaction at the payment gateway (iPay.ua), and redirects the browser to the checkout page.

Not called by the STB directly.

path Parameters
paymentReference
required
string
Example: 01BX5ZZKBKACTAV9WEVGEMMVS0

Unique payment reference (ULID) returned by POST /customers/{customerId}/payment.

Request Body schema: application/x-www-form-urlencoded
required
rate
required
string

Name of the selected subscription plan.

nonce
required
string

CSRF token issued with the payment form page. Must match the value stored in the session; the request is rejected if it does not.

Responses

Payment result callback

Browser-facing endpoint. The payment gateway redirects the user here after checkout completes or is cancelled. Not called by the STB directly.

{result} is ok when the user completed the checkout flow, or nok when they cancelled or the checkout failed. In both cases the server queries the payment gateway for the authoritative status and renders a result page.

When the gateway confirms a successful payment:

  • The customer's expires is extended by the purchased plan's duration.
  • Speed limits are updated to the plan's values.
  • The WireGuard server picks up the changes within 10 seconds.

If the browser redirect is missed (e.g. the user closes the tab), a background process polls the payment gateway every 10 seconds and applies the same subscription update automatically for up to 24 hours after the payment link was created.

path Parameters
paymentReference
required
string
Example: 01BX5ZZKBKACTAV9WEVGEMMVS0

Unique payment reference (ULID) returned by POST /customers/{customerId}/payment.

result
required
string
Enum: "ok" "nok"

Outcome indicator from the payment gateway redirect.

  • ok — user completed checkout (gateway is queried for authoritative status)
  • nok — user cancelled or checkout failed

Responses