DejaVPN for Providers

Integration guide · for app version 2.1 and later

In short: give each user one HTTPS link. When DejaVPN opens it, answer with a JSON list of OpenVPN configs and a few standard headers (the same ones Xray clients such as Happ and v2rayNG read). DejaVPN then keeps the servers up to date, shows data use and expiry, and enforces your device limit. No SDK, no account with us, no fee.

1. The subscription link

Each user gets one link, unique to them:

https://your-domain.com/open/<token>

Users add the link by pasting it, scanning it as a QR code, or tapping a one-tap link on your website or bot:

dejavpn://add?url=https%3A%2F%2Fyour-domain.com%2Fopen%2F<token>

The url parameter is the subscription link, URL-encoded. On a device with DejaVPN installed, the link opens the app with the subscription ready to add.

2. What DejaVPN sends

The app requests the link with GET when the user adds it, when the app opens (if the user keeps "Update servers on open" on), when they tap Update Now, and before connecting. Every request carries:

HeaderExampleMeaning
x-hwida3f9…Device ID: a one-way hash, stable per device and app install. Use it for device limits.
x-device-osAndroidAndroid, Windows, Linux or iOS.
x-ver-os15Operating system version.
x-device-modelPixel 9Device model, for showing the user their devices.
User-AgentDejaVPN/2.1.4 (Android 15)App and version.

These are the same header names Happ uses, so panels that already support Happ's device limits understand them without changes. On Android, the same device ID is also sent to your OpenVPN server in the handshake as UV_HWID, so an auth-user-pass-verify script can check it too.

3. What to answer

Status codes

CodeWhat DejaVPN does
200Reads the servers below and replaces the saved list (new servers appear, removed ones go, changed addresses update).
403Plan not usable right now. Keeps the saved servers but shows why, from subscription-status: limited, expired, device limit or disabled.
404 / 410Subscription deleted. Shown as deleted; the user can remove it.
5xx, timeoutTemporary problem. Keeps the saved servers and tries again later.

Response body (JSON)

{
  "servers": [
    {
      "id": "de-fra-1",
      "name": "Germany · Frankfurt",
      "country": "DE",
      "host": "203.0.113.10:1194",
      "ovpnConfig": "client\ndev tun\nproto udp\nremote 203.0.113.10 1194\n…",
      "username": "user123",
      "password": "secret"
    }
  ]
}
FieldMeaning
serversrequiredThe user's servers. Order is kept.
idrecommendedStable ID per server. Keep it the same when the address changes, so the app knows it's the same server (and keeps the user's choice).
namerecommendedShown in the list. Starting with a country name ("Germany · Frankfurt") also gives it a flag.
countryoptionalISO code (DE, NL…) for the flag; overrides the guess from the name.
ovpnConfigrequiredA complete OpenVPN client config, inline certificates included. Servers without one are skipped.
hostoptionalThe server's address, used for ping before connecting if the config has several remotes.
username / passwordoptionalFor configs that use auth-user-pass. The app sends them to the server when connecting.

For safety, DejaVPN never runs scripts from a config: options that would run programs or read files on the user's device (such as up, down, script-security, plugin) are removed or ignored.

Response headers

HeaderExampleShown as
profile-titleMyVPN Premium or base64:…The subscription's name.
subscription-userinfoupload=0; download=1073741824; total=53687091200; expire=1795956650Data used (upload + download) of the limit (total, bytes; 0 = unlimited), and the end date (expire, Unix seconds; 0 = never).
subscription-statusactiveactive, on_hold, limited, expired, device_limit or disabled.
x-hwid-limit3Devices allowed (0 = unlimited).
x-hwid-devices1Devices registered so far.
support-urlhttps://t.me/your_supportA Contact Support item in the subscription's menu (https or mailto only).
announceNew servers in Turkey this week.One line of news under the subscription's name.
profile-update-interval6How often (hours, 1–24) the app refreshes the subscription in the background.

The user details can also be put in the body, PasarGuard-style, under "user": data_limit, used_traffic, expire, status, hwid_limit, hwid_count. Headers win when both are present.

4. Device limits

  1. On each request, look up x-hwid for the user's token.
  2. Known device, or still under the limit: register it and answer 200.
  3. Over the limit: answer 403 with subscription-status: device_limit and the x-hwid-limit / x-hwid-devices headers. DejaVPN tells the user to remove a device in your bot or panel, and keeps the subscription so it works once a slot is free.

5. Check your integration

curl -i https://your-domain.com/open/<token> \
  -H "x-hwid: test-device-1" -H "x-device-os: Android" \
  -H "x-device-model: Test" -H "User-Agent: DejaVPN/2.1.4 (Android 15)"

You should see 200, your headers, and a JSON body with a servers list where each server has an ovpnConfig. Then add the link in DejaVPN and connect.

6. Verified partners

Everything above is free for every provider. Verified partners also get a verified seal, server names and badges, notices, fallback domains, private links and more. See DejaVPN Partners →

Questions

Integration help: [email protected].