Skip to content

Customer Panel Guide

This guide walks you, the Surf Shield customer (a VPN operator or app vendor), through the panel UI end-to-end so you can ship a branded VPN app without touching any backend code. All actions below are available under sidebar.customer in the left menu after you log in.

If you already have your own billing / admin system and want to automate everything programmatically, see the REST API Reference — every page here has a matching API endpoint.


1. Sign up & activate the customer role

  1. Open the panel landing page, click Get Started Free / Sign up, and create your account.
  2. After email verification, contact Surf Shield support ([email protected]) to be upgraded to the Customer role. Administrators can also grant it from Admin → Manage Users.
  3. Once you log back in, the sidebar shows a new Customer section with three pages:
    • Applications — one row per VPN product you operate.
    • Clients — the end users of each application.
    • Batch Create Clients — provision many users at once (e.g. for resellers).
  4. A Wallet item is available to every role. Top it up before creating clients — each client's traffic is deducted from the parent application's quota, which is paid from your wallet.

2. Applications

An Application represents one VPN product (e.g. your Android app, your iOS app, your corporate VPN). Every application has:

  • A unique packageName (e.g. com.example.myvpn) and a human-friendly name.
  • A class integer for your own tiering (0 = free, 1 = silver, …).
  • A global total_traffic budget (in GB) shared by all clients of the app.
  • A read-only used_traffic and total_clients counter.
  • An API Key auto-generated on creation.

Creating an application

  1. Go to Customer → Applications.
  2. Click Add, fill the form:
    • Package Name — must be globally unique.
    • Name — shown in wallet ledgers.
    • Class — e.g. 0.
    • Status — toggle on to activate.
    • Total Traffic (GB) — the quota your clients share. Leave it at 0 for unlimited but bear in mind billing will be on real usage.
  3. Click Edit. The new row appears in the table; select it and click Copy API Key to copy its X-Api-Key.

Editing & deleting

Select the row and use the vertical Actions buttons. Editing lets you change any field except the API key. Deleting terminates every associated client immediately.

How the API key works

  • The key is a 32-character random string; treat it as a secret.
  • Never ship it in your mobile/desktop app. Call the REST API from your own backend and let your backend proxy requests to the panel.
  • Rotate it via Admin → Manage Users if a leak is suspected (a new key invalidates the old one immediately).

Usage from your backend:

GET /webapi/application/clients?applicationId=<your-application-uuid>
X-Api-Key: <copied-key>

See the full surface in the REST API reference.


3. Clients (end users)

A Client is one VPN end-user. The panel stores:

Field Description
username Unique within your application.
application Which Application the client belongs to.
expiry_date When the subscription ends (UTC).
traffic Allowance in bytes; -1 = blocked, 0 = unlimited.
used_traffic Live usage mirrored from node telemetry.
max_online_ips Concurrent devices; 0 = unlimited.
download_speed_limit / upload_speed_limit Mbps caps per connection.
type REGULAR (normal VPN) or TUNNEL (fixed-endpoint tunnel).
class Your own tier int.
status Active / disabled toggle.

Creating a client (UI)

  1. Customer → ClientsAdd.
  2. Select the target Application from the dropdown.
  3. Enter a unique Username (often user_<uuid> or a real email).
  4. Pick Expiry Date and Traffic (in GB, step 0.01; -1 to provision in a blocked state).
  5. Fill speed limits and concurrent devices (max_online_ips).
  6. Leave Client Type on REGULAR unless you know you need a site-to-site tunnel.
  7. Save.

Updating, banning, un-banning

Partial edits are supported: you only have to set the fields you want to change. To instantly block a user set traffic = -1 and untick Status. To top them up set traffic = <new-allowance> and used_traffic = 0.

Viewing live data

The clients table shows currentIps (the IPs currently online) and usedTraffic in near-real-time (updated from each node every 30 s). Click the row to reveal actions:

  • GeoIP — look up an IP via MaxMind (country, ASN, organization) to investigate abuse.
  • Offline Subscription — download an encrypted .leafsub file the user can import without internet access (see Offline subscriptions).

Batch-create clients

Customer → Batch Create Clients lets you generate N clients in one shot — useful for resellers:

  1. Choose the target application.
  2. Pick a username prefix (e.g. vendor_2025_) and a count.
  3. Set the shared traffic / expiry / speed limits.
  4. Click Export to CSV after generation to hand the list (with per-user UUIDs) to your reseller.

Filter by application

The Filters panel on the left lets you narrow the table to one or more applications, which is handy when you have multiple VPN products.


4. Handing the clientId to your app

Each client has a UUID (id). The end-user's app calls updateSubscription(<uuid>) through the SDK, which then fetches the Leaf .conf from the panel and starts the VPN.

Common delivery patterns:

  • Signup flow in your app — your backend calls POST /webapi/application/clients and returns the UUID to the app.
  • Magic link / deep link — encode the UUID in leafvpn://install?clientId=<uuid> (desktop, URL-safe base64) or leafvpn://install?profile=<base64-uuid> (Android). Both sample projects handle these out of the box.
  • QR code — encode the deep link URL as a QR; users scan it inside the app.

5. Offline subscriptions (.leafsub)

For regions with restricted network access where the panel's API may be blocked, you can pre-sign an encrypted bundle so the user imports it once offline and the SDK consumes it without any network call to the panel.

  1. Select the client row in Customer → Clients.
  2. Click Offline Subscription.
  3. Choose:
    • Encrypt — wraps the bundle with a passphrase (AES-GCM).
    • Passphrase — any string; you give it to the user out-of-band.
    • TTL Days — how long the bundle remains valid.
  4. A .leafsub file is downloaded.

On the user's device:

  • Android — open the file with your app (the .leafsub MIME is registered in the sample's manifest).
  • Desktop — double-click or open via leafvpn://install?profile=...; the Tauri sample intercepts it through tauri-plugin-single-instance + tauri-plugin-deep-link.

Programmatic endpoint (if you have the customer API key):

GET /api/v1/public/subs/<clientId>/offline?encrypt=true&passphrase=<pass>&ttlDays=30

6. Wallet & billing

Wallet (in the shared sidebar section) lets you:

  • Top up via NOWPayments (BTC, USDT-TRC20, TRON, TON, etc.).
  • See every transaction (deposits and per-client traffic deductions).
  • Request payouts if you are also a provider.

Charges happen continuously while your clients consume bytes. If an application's wallet balance hits zero all its clients are auto-suspended; they are reactivated when you top up.


  1. Create one application per environment (staging, production) so you can test without affecting live users.
  2. Back your API key with a Vault / Doppler / AWS Secrets Manager entry — never commit it.
  3. Automate provisioning — have your signup webhook call POST /webapi/application/clients and deep-link the UUID straight into the app.
  4. Automate suspension — on non-payment, call PUT /webapi/application/clients/<uuid> with { "traffic": -1, "is_active": false }.
  5. Monitor — subscribe to the panel's ping endpoint (/api/v1/public/health) and Slack-alert if clients stack up in a blocked state.
  6. Rotate the API key every 90 days (via admin).

8. Troubleshooting

Symptom Likely cause Fix
Client created but app shows updateSubscription failed Wrong clientId, or is_active=false, or traffic=-1 Double-check the row in the panel; make sure status toggle is on and traffic != -1.
401 Unauthorized from the REST API API key wrong or application inactive Re-copy the API key; make sure the application's status toggle is on.
User hits daily quota too early GEOIP routing bypass misconfigured Check bypass_geoip_list in LeafPreferences; YouTube & Netflix are not bypassed by default.
Client online IPs show 0.0.0.0 Client hasn't connected yet Wait ≤30 s for the next node telemetry tick.
Cannot delete an application It still has clients Delete its clients first (select them all in Customer → Clients and bulk-delete).

9. Roles summary

Role Can do
User Sign up, view profile, top up wallet.
Customer (this guide) Create applications, generate API keys, manage clients, download offline subscriptions.
Provider Register nodes, monitor telemetry, receive payouts.
Admin Everything + manage users / roles / withdrawals / core binary updates.

10. Next steps