# Provider cabinet > What the FlowLock provider cabinet gives you and how to connect your subscriptions to it in five steps. The provider cabinet on flowlock.cc links your subscriptions with the FlowLock app for Windows, macOS and Linux. It is free, with limits; [“Unlimited”](https://flowlock.cc/en/docs/limits.md) lifts them for 1000 ₽ a month. ## What you get - **Your contacts in the app.** Support, email and Telegram are shown on the subscription card and in “About the provider”. - **Statistics.** How many devices use your subscriptions, by system, growth by month, active in the last 30 days. - **App management** through subscription headers: an info block with a button, a renewal reminder, moving the subscription to a new domain, a fallback address, ping, auto-update and fragmentation settings, and more. - **Notifications and commands.** A message to all users or to selected devices, “refresh the subscription”, “change the domain”, “import data”, “change settings”. - **Limited and HWID links.** A subscription from such a link can be added to only N devices, and the user doesn't see the subscription address. All of this works only for **verified** subscriptions: the subscription carries your ID, and its domain is verified in your cabinet. Someone else's ID in someone else's subscription gives nothing: the subscription's domain must belong to the same cabinet. ## Getting started 1. **Sign in** to your FlowLock account on flowlock.cc (or sign up) and open the [provider cabinet](https://flowlock.cc/en/provider/) → “Turn on the cabinet”. You get a **provider ID**: 10 characters, for example `k7m2x9q4bd`. 2. **Fill in the contacts**: the name (users see it), a support link, email, Telegram. 3. **Add the domain** you serve subscriptions from (for example `sub.example.com`) and verify it with a TXT record or a file on the website. Details are on the [“Domains”](https://flowlock.cc/en/docs/domains.md) page. 4. **Add the ID to the subscription** as a response header, a line in the body or in the link fragment, see [“ID in the subscription”](https://flowlock.cc/en/docs/provider-id.md). 5. Done. FlowLock apps with your subscription appear in the statistics after their first subscription refresh. Then, if you like: [app management](https://flowlock.cc/en/docs/app-management.md), [notifications and commands](https://flowlock.cc/en/docs/messages.md), [limited links](https://flowlock.cc/en/docs/install-links.md) and the [API](https://flowlock.cc/en/docs/api.md). > **Without a cabinet** FlowLock still reads the subscription as usual: servers, `profile-title`, > `subscription-userinfo`, `support-url`, `announce`, routing rules and the colour theme. The cabinet adds what > requires trust in the provider. The list of headers that work without an ID is on the > [“Subscription headers”](https://flowlock.cc/en/docs/headers.md) page. ## If the cabinet doesn't open Provider cabinets are being turned on gradually. If the cabinet page says the feature is off for now, prepare your subscription using this documentation and come back later. --- # ID in the subscription > Three ways to pass your provider ID to the app: a response header, a line in the subscription body, or the link fragment. The app recognises your subscription by the **provider ID**: 10 lowercase Latin letters and digits, shown in the cabinet's overview. Any of the three ways below will do. If several are present, the app takes the first one in this list. ## Response header The best way, if your panel supports custom headers: ``` flowlock-provider: k7m2x9q4bd ``` In Remnawave: “Subscription settings” → “Additional response headers” (`customResponseHeaders`), name `flowlock-provider`, value: your ID. Other clients skip an unknown header, so there is no need to send it to FlowLock only. ## Line in the subscription body For link-list and base64 subscriptions (in base64, inside the encoded text), within the first 50 lines. Other clients treat such a line as a comment: ``` #flowlock-provider: k7m2x9q4bd vless://… vless://… ``` Spaces are allowed between `#`, the name and the colon, and the name is case-insensitive. Lines longer than 1024 bytes are skipped. JSON subscriptions (Xray, sing-box) have no such line: use the header or the fragment. ## Subscription link fragment When you can change neither the headers nor the body, add the ID to the link you give the user: ``` https://sub.example.com/abc123#My VPN?flowlock-provider=k7m2x9q4bd https://sub.example.com/abc123#flowlock-provider=k7m2x9q4bd ``` Browsers and apps don't send the fragment (everything after `#`) to the server, so the panel never sees it. ## Good to know - The ID isn't a secret: without a [verified domain](https://flowlock.cc/en/docs/domains.md) it unlocks nothing. - Case doesn't matter: `K7M2X9Q4BD` = `k7m2x9q4bd`. - The app remembers the ID from the last successful subscription refresh. Remove the ID from the response and the subscription is ordinary again. - FlowLock doesn't read Happ's `providerid`: FlowLock has its own ID. Add `flowlock-provider` next to it. ## How to check Once the ID is in the subscription and the domain is verified, refresh the subscription in FlowLock. Within a minute the device appears in the cabinet under “Devices”, and your contacts appear on the subscription card. If a person turned off “Tell the provider I'm connected”, their device won't show up in the statistics: that is their right (see [“Privacy”](https://flowlock.cc/en/docs/privacy.md)). --- # Domains and ownership checks > How to verify a subscription domain with a TXT record or a file, what the statuses mean, and why the exact name is what gets verified. A subscription domain has to be verified: that way nobody can pose as you by putting your ID into their own subscription. FlowLock stores the name of the verified domain and its SHA-256 hash; the apps tell the server only the hash of the domain the subscription came from. ## Add a domain 1. Cabinet → “Domains” → enter the name (`sub.example.com`) or a whole subscription link: the cabinet takes the domain from it. 2. Verify it in **one** of the ways below. The cabinet shows ready-made values to copy. 3. Press “Check”, or just wait: the cabinet checks a new domain by itself every hour for the first 72 hours. ## TXT record At your registrar or in your DNS panel (Cloudflare and others): ``` _flowlock.sub.example.com. TXT "flowlock-provider=k7m2x9q4bd" ``` The record name is `_flowlock.` in front of your domain. The subdomain may have any number of other TXT records: the cabinet looks among them for the one equal to `flowlock-provider=`. ## File on the website The file `https://sub.example.com/.well-known/flowlock-provider` with the text: ``` flowlock-provider=k7m2x9q4bd ``` The file must be served directly from this domain: port 443, a valid certificate, status 200, no redirects, at most 4 KB. A domain that points to a private address (`10.x`, `192.168.x` and so on) can't be verified this way. ## Statuses | Status | What it means | | ------------------------ | ---------------------------------------------------------------------------------------------------- | | pending (`pending`) | the domain is added, no check has passed yet | | verified (`verified`) | everything works | | check failed (`failing`) | the last check failed; subscriptions still work for now | | lost (`lost`) | three failures in a row, over at least 48 hours; subscriptions from the domain work as ordinary ones | If a check fails, the cabinet gives the reason: there is neither a record nor a file; the record exists but with a different ID; DNS didn't answer; the file is served with a status other than 200; the file couldn't be downloaded; the domain points to a private address. ## Important - The **exact name** is verified: `sub.example.com` and `example.com` are different domains, and `www.` is separate too. The port doesn't matter: `sub.example.com:2096` = `sub.example.com`. - Internationalised domains can be entered as they are (`подписка.рф`): the cabinet converts them to punycode. - An IP address can't be verified: subscriptions served by IP work as ordinary ones. - **Don't remove** the record or the file: the cabinet re-checks the domain once a day. A lost domain comes back by itself as soon as a check passes again. - Several providers can verify the same domain, each with their own TXT record (for example, a shared panel). - Up to 50 domains per cabinet, and up to 20 manual checks per hour. Addresses for [moving a subscription](https://flowlock.cc/en/docs/app-management.md) (`new-url`, `new-domain`, `fallback-url`), for the “Change the address” command and for [limited links](https://flowlock.cc/en/docs/install-links.md) must also be on your verified domains. --- # Subscription headers > What FlowLock reads from any subscription's response (name, traffic and expiry, support, announcement, refresh interval) and what it sends to the panel itself. FlowLock reads these parameters from **any** subscription; no provider ID is needed for them. The names are the common ones (Remnawave, Marzban, 3x-ui and other panels already send them), so usually there is nothing to set up. The parameters come as **response headers** of the subscription. For link-list and base64 subscriptions they can also go as a **line in the body**, `#name: value`, within the first 50 lines; a header wins over a line with the same name. Text can be encoded as `base64:…` (Remnawave does this with `rwEncodeBase64:`). ## What is read | Parameter | What it does | | ------------------------- | --------------------------------------------------------------------------------------- | | `profile-title` | subscription name (text or `base64:`) | | `subscription-userinfo` | traffic and expiry: `upload=…; download=…; total=…; expire=` | | `support-url` | the “Support” button | | `profile-web-page-url` | the “Subscription page” button | | `announce` | the “From the provider” announcement (up to 200 characters, text or `base64:`) | | `profile-update-interval` | how often to refresh the subscription, in hours | | `routing` | the subscription's routing rules, see [“Routing”](https://flowlock.cc/en/docs/routing.md) | | `routing-enable` | `0`: don't apply the subscription's routing rules (the user's own rules are left alone) | | `flowlock-theme` | a colour theme, if the user agreed, see [“Themes”](https://flowlock.cc/en/docs/themes.md) | | `flowlock-provider` | your provider ID, see [“ID in the subscription”](https://flowlock.cc/en/docs/provider-id.md) | Sample response: ``` HTTP/1.1 200 OK profile-title: base64:0JzQvtC5IFZQTg== subscription-userinfo: upload=0; download=1073741824; total=107374182400; expire=1798761600 profile-update-interval: 12 support-url: https://t.me/myvpn_support announce: A new server in the Netherlands is now on the list ``` `total=0` or no `total` means traffic without a limit (“unlimited”); `expire=0` or no `expire` means no expiry date. Extended parameters (the info block, “Renew”, moving to a new domain, app settings) work only for a verified subscription. They are described on the [“App management”](https://flowlock.cc/en/docs/app-management.md) page. ## Subscription formats FlowLock understands base64 and link lists (`vless://`, `vmess://`, `trojan://`, `ss://`, `hysteria2://`/`hy2://` and others), Xray JSON and sing-box JSON. In JSON subscriptions the routing rules are taken from the JSON itself (`routing` in Xray, `route` in sing-box). ## What FlowLock sends to the panel - **User-Agent**: its own, like `FlowLock/1.2.0 (macOS; arm64)`. Details and compatibility are on the [“User-Agent”](https://flowlock.cc/en/docs/user-agent.md) page. - **HWID headers** for device limits (as in Remnawave): `x-hwid`, `x-device-os`, `x-ver-os`, `x-device-model`, as long as the user has “Send HWID” turned on. A subscription can require the HWID always (`subscription-always-hwid-enable`, needs an ID). FlowLock downloads subscriptions directly, outside the VPN: many panels don't answer requests from VPN server addresses. ## “Add to FlowLock” button You can put a link on the subscription page that adds the subscription to the app: ``` flowlock://add/https://sub.example.com/abc123 https://flowlock.cc/add/#url=https%3A%2F%2Fsub.example.com%2Fabc123&name=My%20VPN ``` The first one opens the app (it asks for confirmation), the second one opens the website, which adds the subscription to the user's FlowLock account. The other commands are on the [“flowlock:// links”](https://flowlock.cc/en/docs/links.md) page. --- # App management > Subscription parameters a provider uses to manage FlowLock: info block, renewal, moving, fallback address and app settings; what FlowLock doesn't read and why. Parameters come as a **subscription response header** or a **line in the body**, `#name: value` (a header wins over a line with the same name). The names are Happ's: if your panel already sends them for Happ, FlowLock understands them without any setup. Text can be encoded as `base64:…`. Boolean values: `true` or `1` means yes, `false` or `0` means no. The parameters on this page work **only for a verified subscription**: it carries your [ID](https://flowlock.cc/en/docs/provider-id.md), and its domain is [verified](https://flowlock.cc/en/docs/domains.md) in your cabinet. Parameters that work for any subscription are on the [“Subscription headers”](https://flowlock.cc/en/docs/headers.md) page. ## Example ``` HTTP/1.1 200 OK profile-title: base64:0JzQvtC5IFZQTg== subscription-userinfo: upload=0; download=1073741824; total=107374182400; expire=1798761600 support-url: https://t.me/myvpn_support flowlock-provider: k7m2x9q4bd sub-info-color: blue sub-info-text: A new server in the Netherlands is now on the list sub-info-button-text: Learn more sub-info-button-link: https://myvpn.example/news sub-expire: 1 sub-expire-button-link: https://t.me/myvpn_bot?start=renew fallback-url: https://sub2.example.com/abc123 ping-type: tcp ``` ## Extended parameters | Parameter | Value | What it does | | --------------------------------- | ------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `new-url` | link | permanently changes the subscription address for everyone. The new address must be on your verified domain; if the subscription doesn't load from it, the app goes back to the old one | | `new-domain` | domain | changes only the domain (the path and token stay). Also only your verified domain | | `fallback-url` | link | a fallback address on your verified domain: if the main one doesn't answer within 9 s, fails with a network error or returns HTTP 300 to 599, the app tries the fallback | | `serverDescription` | up to 30 characters | a caption under the server name: in the server link `vless://…#Germany?serverDescription=RmFzdA==` (base64) or `meta.serverDescription` in a JSON subscription | | `sub-info-text` | up to 200 characters, `0` removes it | an info block on the subscription card | | `sub-info-color` | `blue` (default), `green`, `red` | the info block's colour | | `sub-info-button-text` | up to 25 characters | a button in the info block (no button without it) | | `sub-info-button-link` | `https://…` or `tg://…` | where the button leads | | `sub-expire` | `1` | a “Subscription ends in N days” banner 3 days before `expire`, and “Subscription has ended” after it | | `sub-expire-button-link` | `https://…` or `tg://…` | a “Renew” button in that banner | | `notification-subs-expire` | `1` | a system notification 3 days before, 1 day before and on the day of expiry | | `subscription-always-hwid-enable` | `1` | this subscription always sends the HWID, even if the user turned off “Send HWID”. The user sees the explanation “required by the provider” and can only delete the subscription | ## App settings The same keys can be sent with the “Change settings” command (see [“Notifications and commands”](https://flowlock.cc/en/docs/messages.md)). | Parameter | Value | What it changes | Where | | -------------------------------------- | ------------------------------------ | ------------------------------------------------ | ----- | | `subscription-autoconnect` | `1` / `0` | connect when the app starts | all | | `subscription-ping-onopen-enabled` | `1` / `0` | ping servers when the app starts | all | | `subscription-auto-update-enable` | `1` / `0` | auto-update of **this** subscription | all | | `subscription-auto-update-open-enable` | `1` / `0` | refresh subscriptions when the app starts | all | | `ping-type` | `proxy`, `proxy-head`, `tcp`, `icmp` | ping method (`proxy-head` = `proxy`) | all | | `check-url-via-proxy` | `https://…` | the check address for ping through the proxy | all | | `proxy-ping-timeout` | seconds, 1 to 10 (more counts as 10) | ping timeout | all | | `change-user-agent` | string up to 256 | User-Agent for downloading **this** subscription | all | | `fragmentation-enable` | `1` / `0` | TLS ClientHello fragmentation | all | | `fragmentation-packets` | `tlshello` or `1-3` | which packets to split | macOS | | `fragmentation-length` | `50-100` | piece length | macOS | | `fragmentation-interval` | `10-20` | pause between pieces, ms | macOS | | `subscriptions-sort-type` | `without`, `ping`, `alphabet` | server order | all | | `subscription-always-hwid-enable` | `1` / `0` | see above | all | | `notification-subs-expire` | `1` / `0` | see above | all | ### How the user sees it Next to the setting there is “Set by the provider “My VPN”” and a “Restore mine” button. If the user restored their own value, the same header no longer overrides it; a new value does. If the user deletes the subscription, the settings you set go back to their previous values. ## What FlowLock doesn't read | Parameter | Why | | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------- | | `custom-tunnel-config`, `socks-auth-*`, `http-auth-*`, `dns-from-json-enable` | they open the local proxy to the outside, change DNS or replace the whole core configuration, which breaks the user's protection | | `proxy-enable`, `tun-enable`, `tun-mode`, `tun-type` | the user chooses the connection mode (TUN needs administrator rights) | | `exclude-routes`, `exclude-routes-set`, `per-app-proxy-*` | they let traffic go around the VPN | | `hide-settings` | the user has the right to see what runs on their computer; [limited links](https://flowlock.cc/en/docs/install-links.md) hide the subscription address | | `server-address-resolve-*`, `subscription-request-timeout`, `subscription-autoconnect-type`, `proxy-ping-mode`, `ping-result`, `manual-block-user-agent` | FlowLock has no such setting, or it is the user's choice | | `noises-*`, `mux-*`, `sniffing-enable`, `fragmentation-maxsplit`, `no-limit-*`, `user-agent-geo-files` | parameters of another core (Xray) or of Happ modes | | `color-profile`, `hide-vpn-icon`, `subscriptions-collapse`, `subscriptions-expand-now`, `subscription-pin`, `dont-use-filter`, `app-auto-start`, `xray-tun-*`, `include-all-networks-enable` and other mobile ones | iOS/Android only, or meaningless on a computer; FlowLock has its own themes (`flowlock-theme`) | | `providerid` | Happ's ID; FlowLock has its own, `flowlock-provider` | Neither a header nor a command lets the provider change: the user's routing rules and “all direct”, DNS, local proxy ports and passwords, “Allow connections from the network”, the global “Send HWID” switch, the connection mode, diagnostics and the account. --- # Subscription colour theme > The flowlock-theme header: FlowLock interface colours for the people on your subscription, the value format and the readability rules. A provider can send a **colour theme** with the subscription: the colours of the FlowLock interface. The app shows it to the people on your subscription only if they agree: when the theme first appears, FlowLock asks once, “ offers its own theme. Apply it?”. No provider ID is needed for a theme. The format is FlowLock's own. FlowLock doesn't read other theme formats (Happ `color-profile` and others). ## How to send it **Response header** (in Remnawave: one line in Response Headers): ``` flowlock-theme: accent=#1F7A4D/#4CC38A; bg=#F4F7F5/#0E1411; card=#FFFFFF/#17201B; text=#10231A/#E6EFE9; muted=#5B6B62/#93A39A ``` **Line in the body**: if you can't add headers, as the first line of a link-list or base64 subscription: ``` #flowlock-theme: accent=#1F7A4D/#4CC38A; bg=#F4F7F5/#0E1411 ``` The header goes to every client: other clients skip an unknown header, so there is no need to guess by User-Agent. ## Value Fields are separated by `;`, each is `key=colour`. A colour is `#RRGGBB` or a pair `#light/#dark`: the first for the app's light theme, the second for the dark one. A single colour without `/` is used for both. | Key | What it colours | | -------- | ------------------------------------------------- | | `accent` | buttons, switches, the connection ring, selection | | `bg` | window background | | `card` | cards, panels, list rows | | `text` | main text | | `muted` | secondary text | All keys are optional. Unknown keys and invalid colours are skipped, and the rest works. `none` or an empty value means no theme. A header longer than 512 bytes or a body line longer than 1024 bytes isn't read (Remnawave cuts headers to 512 characters). The format has no images, logos, fonts, gradients or transparency, and never will. ## Readability FlowLock checks contrast (WCAG) and adjusts the colours when needed: text at least 4.5:1 against the background and cards, secondary text and accent at least 3:1, and the text on the accent is picked automatically. The background must suit its side: a light one for the light theme, a dark one for the dark theme. A single `bg=#FFFFFF` suits only the light side, and in the dark theme the app keeps its own background. If you want both sides, give a pair `bg=#light/#dark`. If anything was adjusted, the person sees “The provider theme was adjusted for readability” in the appearance settings. ## What the person sees - The person chooses the mode (system, light or dark theme); the provider's theme doesn't switch it. - The theme changes along with subscription refreshes without asking again. If it disappears from the response, it disappears from the app too, and the person's own accent comes back. - Windows and Linux use all five colours; macOS uses the accent, background and cards of the main window. - The person's own theme wins over the provider's (see [“Themes and sharing them”](https://flowlock.cc/en/docs/user-themes.md)). --- # Subscription routing rules > How a provider sends rules for what goes through the VPN and what goes direct: a Happ profile in the routing header, Xray and sing-box JSON. A provider can send **routing rules** with the subscription: which sites and addresses go through the VPN, which go direct, and which are blocked. FlowLock applies them together with the user's own rules; the user's rules win. No provider ID is needed for this. ## Happ profile The same format Remnawave serves for Happ, as the `routing` header or a line in the body: ``` routing: happ://routing/add/ routing: happ://routing/onadd/ ``` - `add`: the subscription's rules simply work together with the person's rules. - `onadd`: the same, and if the profile has `GlobalProxy: false`, the app **offers** “Selective” mode (only what's in the rules goes through the VPN). It never switches the mode by itself. - `routing: off` or `routing-enable: 0`: don't apply the subscription's rules. Domains in a Happ profile (as in Xray) match as substrings, and FlowLock reads them the same way. ## JSON subscriptions - **Xray JSON**: rules from `routing.rules`. - **sing-box JSON**: rules from `route.rules`. ## What the person sees - The subscription's rules are shown as a separate list in the route editor, and each one can be turned off with a checkbox. - A subscription refresh changes **only** the subscription's rules; the person's own rules are kept. - Order: the user's block, “via VPN” and “direct” rules, then the same three lists from the subscription, then the routing mode. ## geosite and geoip categories Rules can refer to `geosite:` and `geoip:` categories. FlowLock's standard databases are SagerNet's, and categories missing there (for example `ru-blocked`) come from runetfreedom. A person can add their own databases (see [“Routes and custom databases”](https://flowlock.cc/en/docs/rules.md)). The links `flowlock://routing/add/…` and `flowlock://routing/onadd/…` add the same rules with a click (see [“flowlock:// links”](https://flowlock.cc/en/docs/links.md)). --- # Limited and HWID links > Subscription links with a device limit, or for a single device by HWID, where the user never sees the subscription address. A **limited link** lets the subscription be added to at most N devices. A **HWID link** works for only one device with the given HWID. ## Create a link 1. Cabinet → “Links” → “New link”: the subscription address (on your [verified domain](https://flowlock.cc/en/docs/domains.md)), the device limit (1 to 1000), a note for yourself, and an expiry date. For a HWID link, also the device's HWID (the limit is then 1). 2. You get two links to the same thing: ``` flowlock://install/a7k2m9x4q8b3n6p5 https://flowlock.cc/i/a7k2m9x4q8b3n6p5 ``` The second one is handy for messengers: the page opens FlowLock or offers to download it. The cabinet also shows a QR code of this link. ## How it works - The subscription address is stored encrypted on the FlowLock server and handed to the app only while the link has places left. A device that already got the link gets it again without using up a place (for a reinstall). - The app asks the person: “Add a subscription from the provider “My VPN”?” Nothing is added silently. - The user doesn't see the subscription address: it can't be copied, shown as a QR code or shared. To their other devices the user carries the link itself, not the address, and each device takes its own place. - No places left: the app says “The subscription administrator has limited the number of devices” and shows your contacts. - For a HWID link the app asks the person whether it may send the HWID if they have “Send HWID” turned off. A different HWID means the link won't work. ## Management The link list shows how many places are taken. For each link you can: - see its devices and **unlink** any of them, which frees the place; - change the limit (no lower than the number of devices on the link) and the note; - turn it off and on again; - delete it. > **Unlinking doesn't revoke access.** The subscription address already handed out keeps working. To close access, > change the subscription token in your panel. This protects against accidental sharing, not against a determined person: on their own computer the address can be intercepted. ## Through the API ```sh # limited link for 3 devices curl -s -X POST https://api.flowlock.cc/v1/provider/installs -H "Authorization: Bearer $FLOWLOCK_KEY" \ -H 'Content-Type: application/json' \ -d '{"url": "https://sub.example.com/abc123", "limit": 3, "note": "user 1042"}' # HWID link curl -s -X POST https://api.flowlock.cc/v1/provider/installs -H "Authorization: Bearer $FLOWLOCK_KEY" \ -H 'Content-Type: application/json' \ -d '{"url": "https://sub.example.com/abc123", "limit": 1, "hwid": "5f0c…"}' ``` The other calls are in the [API reference](https://flowlock.cc/en/docs/api.md#links). Up to 5000 links per cabinet. --- # Notifications and commands > Messages to users of verified subscriptions: notifications, a window on top and safe commands to the app, recipients, scheduling and limits. Cabinet → “Messages”, or the [API](https://flowlock.cc/en/docs/api.md#messages). Apps fetch messages at launch, after a subscription refresh and every hour while they run, so a message usually arrives within an hour. Only [verified](https://flowlock.cc/en/docs/providers.md) subscriptions receive them. ## Notification - **Title**: up to 100 characters; **text**: up to 2000, plain text. - **Link**: `https://…`, shown as an “Open” button. Optional. - **Translation** into `ru` or `en`: the user sees their own language, otherwise the main text. - **How to show it**: - regular (`optional`): a system notification and a banner on the subscription card; - window on top (`force`): a window over the app. ## Commands | Command | What it does | | --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `update-subscription` | refresh the subscription | | `sub-change` | change the subscription's domain (`domain`) or address (`url`), only to your verified domain; `url` goes to selected devices only (every user has their own address) | | `import-data` | offer an import: a subscription link, server links, a profile, routing rules. **The user always confirms** | | `set-settings` | change settings, with keys from the [“App settings”](https://flowlock.cc/en/docs/app-management.md#app-settings) table | Before changing the address, the app checks that the new domain is verified by your cabinet; if the subscription doesn't load from the new address, the old one comes back. ## To whom and when - **To**: everyone, by system (`windows`, `macos`, `linux`) or selected devices, up to 20, with identifiers from the “Devices” section (you can tick them there and go straight to a message). - **When**: now or on a schedule, up to 30 days ahead. - **Delivery window**: from an hour to 30 days, 7 by default. After it the message is not delivered. - **Cancel** at any time: those who haven't received it yet won't. For each message you can see how many devices received it, saw it, opened the link, did it, declined or failed to do it. ## Limits - Messages to everyone or by system: no more than 2 a day (4 with Unlimited), at most once in 5 minutes. - Messages to selected devices: up to 200 an hour, up to 20 devices each. Up to 500 waiting for delivery. - The app shows at most 3 notifications from one provider a day and one window on top an hour; the rest stay in the notification list on the subscription card. - Advertising and spam are forbidden: the cabinet gets suspended for them. ## API examples ```sh # notification to everyone, with a translation curl -s -X POST https://api.flowlock.cc/v1/provider/messages -H "Authorization: Bearer $FLOWLOCK_KEY" \ -H 'Content-Type: application/json' -d '{ "kind": "notification", "mode": "optional", "title": "Maintenance", "body": "Tonight 23:00 to 00:00 UTC service may be interrupted.", "link": "https://myvpn.example/status", "locales": {"ru": {"title": "Плановые работы", "body": "Сегодня с 02:00 до 03:00 МСК возможны перебои."}}, "target": {"all": true}, "expires_in": 86400}' # refresh the subscription on Windows and Linux on a schedule curl -s -X POST https://api.flowlock.cc/v1/provider/messages -H "Authorization: Bearer $FLOWLOCK_KEY" \ -H 'Content-Type: application/json' -d '{ "kind": "command", "action": "update-subscription", "target": {"os": ["windows", "linux"]}, "send_at": "2026-11-01T09:00:00Z"}' ``` All the fields and more examples are in the [API reference](https://flowlock.cc/en/docs/api.md#messages). --- # Statistics > How many devices use your subscriptions: in total, active in the last 30 days, by system and by month. Cabinet → “Overview”: - devices in total and active in the last 30 days (inactive = total − active), by system; - by month (up to 24): new devices and active ones, by system. Cabinet → “Devices”: a list of devices with a filter by system and activity: the identifier, the system and its version, the FlowLock version, when the device first appeared and when it last checked in. ## What counts as a device A device is one FlowLock installation with your verified subscription. The app checks in as soon as the subscription gets your ID, and after that at most once a day, after a subscription refresh. The device identifier: - **HWID**: if the person turned on “Send HWID” (or the subscription requires the HWID). It is the same HWID your panel gets in the `x-hwid` header. - **Alias**: otherwise. It stays the same for the pair “device + your cabinet” and is linked to nothing else. If a person turns “Send HWID” on or off, their device appears again under a different identifier, and the old record drops out of the active ones after 30 days. ## What the statistics don't include Devices where the person turned off “Tell the provider I'm connected”, and subscriptions without an ID or from an unverified domain. IP addresses, countries, sites and traffic are never in the statistics, see [“Privacy”](https://flowlock.cc/en/docs/privacy.md). A device that stops checking in is deleted after 180 days; monthly statistics are kept for 24 months. Up to 500,000 devices per cabinet in the statistics. --- # flowlock:// links > Commands of the flowlock:// scheme: connect, disconnect, add a subscription, import, routing rules, limited links and themes. FlowLock registers the `flowlock://` scheme in the system. You can put such a link on a website, in a bot or in a shortcut. The browser itself asks the person whether to open the app. ## Commands | Link | What it does | Confirmation | | ----------------------------------- | ------------------------------------------------------------------------------------ | ------------ | | `flowlock://connect` | connect | no | | `flowlock://disconnect` | disconnect | no | | `flowlock://toggle` | connect or disconnect | no | | `flowlock://open`, `flowlock://` | show the window | no | | `flowlock://quit` | quit the app | no | | `flowlock://add/
` | add a subscription by its address | **yes** | | `flowlock://import/` | import a subscription, servers, a profile or routing rules, depending on the content | **yes** | | `flowlock://routing/add/` | add routing rules (a Happ profile) to the person's rules | **yes** | | `flowlock://routing/onadd/` | the same, and offer “Selective” mode if the profile has `GlobalProxy: false` | **yes** | | `flowlock://install/` | a subscription from a [limited link](https://flowlock.cc/en/docs/install-links.md) | **yes** | | `flowlock://theme/` | a shared [colour theme](https://flowlock.cc/en/docs/user-themes.md) | **yes** | The scheme and the command are case-insensitive, and the slashes after `:` are optional (`flowlock:connect`). Commands with confirmation always show exactly what will be added and wait for “Add” or “Cancel”: FlowLock never runs a link from the browser silently. The worst a stranger's page can do with a command that needs no confirmation is disconnect the VPN. ## Arguments - `add/…`: the subscription address as is (`flowlock://add/https://sub.example.com/abc`) or percent-encoded (`flowlock://add/https%3A%2F%2Fsub.example.com%2Fabc`). Only `http://` and `https://`. - `import/…` and `routing/…`: base64 (standard or URL-safe; trailing `=` are optional). Inside `import`: - an `http(s)://` address: a subscription; - server links, WireGuard/AmneziaWG `.conf`, `.ovpn`: servers; - `happ://routing/add|onadd/…`: routing rules; - a FlowLock profile (JSON): a profile import where you choose the sections. Example: an “Add to FlowLock” button on a subscription page: ```html Add to FlowLock ``` ## Web links Some messengers don't make `flowlock://` clickable. For them there are pages on the website: - `https://flowlock.cc/i/`: a limited link, with an “Open in FlowLock” button and an app download; - `https://flowlock.cc/theme#`: a colour theme with a preview; - `https://flowlock.cc/add/#url=
&name=`: add a subscription to the FlowLock account on the website. --- # FlowLock User-Agent > Which User-Agent FlowLock sends when it downloads a subscription, how to recognise FlowLock in a panel, and what happens if the panel doesn't accept it. When downloading a subscription, FlowLock introduces itself with its own User-Agent: ``` FlowLock/ (; ) ``` | Example | | | ------------------------------- | -------------------- | | `FlowLock/1.2.0 (macOS; arm64)` | macOS, Apple Silicon | | `FlowLock/0.1.0 (Windows; x64)` | Windows | | `FlowLock/0.1.0 (Linux; x64)` | Linux | - System: `macOS`, `Windows`, `Linux`. Architecture: `x64`, `arm64`, `x86`. - FlowLock doesn't send the system version: it would be an extra fingerprint. - The Windows/Linux service, when it refreshed the subscription by itself (right after the computer starts, before the window has been opened), may send a UA without a version: `FlowLock (Windows; x64)`. ## How to recognise FlowLock in a panel Look for a User-Agent that starts with `FlowLock/` or `FlowLock (`. For example, a panel rule condition: “User-Agent starts with `FlowLock`”. There is no need to serve FlowLock a special format: it understands base64, links, Xray JSON and sing-box JSON. ## If the panel doesn't accept FlowLock's User-Agent Some panels answer unknown clients with an HTML page or a 403/406 status. Then FlowLock retries the request once with the compatible User-Agent `v2rayN/7.13.8`, and for the next **7 days** it loads that subscription with it straight away, then tries its own again. There is no retry on 404, 5xx or any other response: a different User-Agent won't help there. It is better to teach your panel to answer FlowLock with the subscription: that way you'll see in the panel's logs how many FlowLock users you have. ## Custom User-Agent - A person can set a User-Agent for one subscription or for all of them; then exactly that one is sent, with no retries. - The provider of a verified subscription can set it with the `change-user-agent` parameter (see [“App management”](https://flowlock.cc/en/docs/app-management.md)). --- # API reference > The provider cabinet API for panels and bots: keys, domains, limited links, messages, devices and statistics, with curl examples. For panels and bots: everything the cabinet has, except API keys and deleting the cabinet. - Address: `https://api.flowlock.cc`. - **API key**: cabinet → “API keys” → “Create a key”. The key (`flp_…`) is shown once; keep it like a password. You can create up to 10 keys and revoke any of them. - The key goes **only in the header**: `Authorization: Bearer flp_…`. A key in the URL is not accepted. - Bodies and responses are JSON, dates are RFC 3339 UTC. An error is an HTTP status plus `{"error": "…", "code": "…"}`. A `429` comes with a `Retry-After` header (seconds). - Lists come in pages: `?cursor=` from the previous response's `next_cursor`. - At most 120 requests per minute. In the examples the key is in an environment variable: ```sh export FLOWLOCK_KEY='flp_…' ``` ## Provider ```sh curl -s https://api.flowlock.cc/v1/provider -H "Authorization: Bearer $FLOWLOCK_KEY" ``` ```json { "id": "k7m2x9q4bd", "name": "My VPN", "support_url": "https://t.me/myvpn_support", "email": "help@myvpn.example", "telegram": "myvpn_bot", "status": "active", "created_at": "2026-10-28T12:00:00Z", "limits": { "domains": 50, "…": 0 } } ``` Change the contacts (an empty string removes a field, except `name`): ```sh curl -s -X PATCH https://api.flowlock.cc/v1/provider -H "Authorization: Bearer $FLOWLOCK_KEY" \ -H 'Content-Type: application/json' -d '{"support_url": "https://t.me/myvpn_support", "telegram": "@myvpn_bot"}' ``` Fields: `name`: 1 to 40 characters; `support_url`: `https://…` or `tg://…`, up to 512; `email`; `telegram`: `@name`, a `t.me` link or a name (5 to 32 characters of `A–Z a–z 0–9 _`). ## Domains ```sh # list curl -s https://api.flowlock.cc/v1/provider/domains -H "Authorization: Bearer $FLOWLOCK_KEY" # add: the response holds the record and the file for verification curl -s -X POST https://api.flowlock.cc/v1/provider/domains -H "Authorization: Bearer $FLOWLOCK_KEY" \ -H 'Content-Type: application/json' -d '{"domain": "sub.example.com"}' ``` ```json { "id": "d1f2a3b4c5d6e7f8", "domain": "sub.example.com", "hash": "…64 hex…", "status": "pending", "created_at": "…", "dns": { "name": "_flowlock.sub.example.com", "type": "TXT", "value": "flowlock-provider=k7m2x9q4bd" }, "file": { "url": "https://sub.example.com/.well-known/flowlock-provider", "body": "flowlock-provider=k7m2x9q4bd" } } ``` ```sh # check now (up to 20 times an hour) curl -s -X POST https://api.flowlock.cc/v1/provider/domains/d1f2a3b4c5d6e7f8/verify -H "Authorization: Bearer $FLOWLOCK_KEY" # delete curl -s -X DELETE https://api.flowlock.cc/v1/provider/domains/d1f2a3b4c5d6e7f8 -H "Authorization: Bearer $FLOWLOCK_KEY" ``` Domain fields: `status` (`pending` | `verified` | `failing` | `lost`), `method` (`dns` | `file`: how it was verified), `verified_at`, `checked_at`, `error`: the reason for the last failure: `no_record` (no record and no file), `wrong_id` (the record exists, but with another ID), `dns_error`, `http_status`, `fetch_error`, `not_public` (the domain points to a private address). ## Links ```sh # create a limited link for 3 devices curl -s -X POST https://api.flowlock.cc/v1/provider/installs -H "Authorization: Bearer $FLOWLOCK_KEY" \ -H 'Content-Type: application/json' \ -d '{"url": "https://sub.example.com/abc123", "limit": 3, "note": "user 1042"}' ``` ```json { "id": "i8c7b6a5d4e3f2a1", "code": "a7k2m9x4q8b3n6p5", "link": "flowlock://install/a7k2m9x4q8b3n6p5", "web_link": "https://flowlock.cc/i/a7k2m9x4q8b3n6p5", "url": "https://sub.example.com/abc123", "domain": "sub.example.com", "limit": 3, "count": 0, "hwid": "", "note": "user 1042", "status": "active", "created_at": "…", "expires_at": null } ``` ```sh # HWID link: limit 1 and the device's HWID curl -s -X POST https://api.flowlock.cc/v1/provider/installs -H "Authorization: Bearer $FLOWLOCK_KEY" \ -H 'Content-Type: application/json' \ -d '{"url": "https://sub.example.com/abc123", "limit": 1, "hwid": "5f0c…"}' # list; one link; change the limit, note, status (active | disabled), address, expiry curl -s https://api.flowlock.cc/v1/provider/installs -H "Authorization: Bearer $FLOWLOCK_KEY" curl -s https://api.flowlock.cc/v1/provider/installs/i8c7b6a5d4e3f2a1 -H "Authorization: Bearer $FLOWLOCK_KEY" curl -s -X PATCH https://api.flowlock.cc/v1/provider/installs/i8c7b6a5d4e3f2a1 -H "Authorization: Bearer $FLOWLOCK_KEY" \ -H 'Content-Type: application/json' -d '{"limit": 5}' # the link's devices, and unlinking one curl -s https://api.flowlock.cc/v1/provider/installs/i8c7b6a5d4e3f2a1/devices -H "Authorization: Bearer $FLOWLOCK_KEY" curl -s -X DELETE https://api.flowlock.cc/v1/provider/installs/i8c7b6a5d4e3f2a1/devices/5f0c… \ -H "Authorization: Bearer $FLOWLOCK_KEY" # delete the link curl -s -X DELETE https://api.flowlock.cc/v1/provider/installs/i8c7b6a5d4e3f2a1 -H "Authorization: Bearer $FLOWLOCK_KEY" ``` `expires_at`: RFC 3339 in the future, or `null` (no expiry). Errors: the address isn't on a verified domain: `422 domain_unverified`; the limit is below the number of devices: `422 limit_below_count`; with `hwid` the limit can only be 1: `400 bad_request`. ## Messages ```sh # notification to everyone curl -s -X POST https://api.flowlock.cc/v1/provider/messages -H "Authorization: Bearer $FLOWLOCK_KEY" \ -H 'Content-Type: application/json' -d '{ "kind": "notification", "mode": "optional", "title": "Maintenance", "body": "Tonight 23:00 to 00:00 UTC service may be interrupted.", "link": "https://myvpn.example/status", "locales": {"ru": {"title": "Плановые работы", "body": "Сегодня с 02:00 до 03:00 МСК возможны перебои."}}, "target": {"all": true}, "expires_in": 86400}' ``` ```json { "id": "m3k9q2x7a1b4c5d6", "kind": "notification", "status": "active", "…": "…" } ``` ```sh # command: refresh the subscription on Windows and Linux on a schedule curl -s -X POST https://api.flowlock.cc/v1/provider/messages -H "Authorization: Bearer $FLOWLOCK_KEY" \ -H 'Content-Type: application/json' -d '{ "kind": "command", "action": "update-subscription", "target": {"os": ["windows", "linux"]}, "send_at": "2026-11-01T09:00:00Z"}' # command: move to a new domain (it must be verified) curl -s -X POST https://api.flowlock.cc/v1/provider/messages -H "Authorization: Bearer $FLOWLOCK_KEY" \ -H 'Content-Type: application/json' -d '{ "kind": "command", "action": "sub-change", "change_type": "domain", "value": "sub2.example.com", "target": {"all": true}}' # command: new settings for two devices curl -s -X POST https://api.flowlock.cc/v1/provider/messages -H "Authorization: Bearer $FLOWLOCK_KEY" \ -H 'Content-Type: application/json' -d '{ "kind": "command", "action": "set-settings", "settings": {"ping-type": "tcp", "fragmentation-enable": true}, "target": {"devices": ["5f0c…", "9b1e…"]}}' # command: offer an import (the user confirms) curl -s -X POST https://api.flowlock.cc/v1/provider/messages -H "Authorization: Bearer $FLOWLOCK_KEY" \ -H 'Content-Type: application/json' -d '{ "kind": "command", "action": "import-data", "data": "https://sub.example.com/abc123", "target": {"devices": ["5f0c…"]}}' # list (with delivery results), one message, cancel curl -s https://api.flowlock.cc/v1/provider/messages -H "Authorization: Bearer $FLOWLOCK_KEY" curl -s https://api.flowlock.cc/v1/provider/messages/m3k9q2x7a1b4c5d6 -H "Authorization: Bearer $FLOWLOCK_KEY" curl -s -X DELETE https://api.flowlock.cc/v1/provider/messages/m3k9q2x7a1b4c5d6 -H "Authorization: Bearer $FLOWLOCK_KEY" ``` Message fields: - `kind`: `notification` | `command`; - notification: `title`, `body`, `link`, `locales` (`ru`/`en`), `mode` (`optional` | `force`); - command: `action` and its fields: `change_type` + `value` (`sub-change`), `data` (`import-data`, up to 16 KB), `settings` (`set-settings`, keys from [“App settings”](https://flowlock.cc/en/docs/app-management.md#app-settings)); - `target`: `{"all": true}`, `{"os": […]}` or `{"devices": […]}`; - `send_at`: optional; `expires_in`: seconds from `send_at` (3600 to 2592000, 604800 by default). In the list: `status` (`scheduled` | `active` | `expired` | `cancelled`) and `counts`: `received`, `shown`, `opened`, `done`, `declined`, `failed`. Errors: `400 bad_request` (the field in `field`), `422 domain_unverified`, `422 bad_setting` (the key in `key`), `429 rate_limited` (anti-spam, `retry_after`), `403 suspended`. ## Devices and statistics ```sh # devices (for choosing recipients): filter by system and active in the last 30 days curl -s 'https://api.flowlock.cc/v1/provider/devices?os=windows&active=30d' -H "Authorization: Bearer $FLOWLOCK_KEY" ``` ```json { "devices": [ { "device": "5f0c…", "device_kind": "hwid", "os": "windows", "os_version": "10.0.26200", "app": "0.4.0", "first_seen": "…", "last_seen": "…" } ], "next_cursor": "…" } ``` `device_kind`: `hwid`: the device's HWID (the same one your panel gets in `x-hwid`); `alias`: an alias, if the user doesn't send the HWID. More on the [“Statistics”](https://flowlock.cc/en/docs/stats.md) page. ```sh curl -s https://api.flowlock.cc/v1/provider/stats -H "Authorization: Bearer $FLOWLOCK_KEY" ``` ```json { "devices": { "total": 1520, "active_30d": 1204, "by_os": { "windows": { "total": 900, "active_30d": 700 }, "macos": { "total": 420, "active_30d": 350 }, "linux": { "total": 200, "active_30d": 154 } } }, "months": [ { "month": "2026-10", "new": { "windows": 120, "macos": 40 }, "active": { "windows": 700, "macos": 350 } } ] } ``` ## Reference data for forms `GET /v1/provider/settings-keys`: the “App settings” keys with their types (`bool`, `int`, `string`, `enum` + `values`), scope (`app`: the whole app, `subscription`: this subscription) and platforms. ## Error codes | code | HTTP | what it means | | --------------------- | ---- | -------------------------------------------------------------------------------------------- | | `unauthorized` | 401 | no key, or the key is wrong or revoked | | `not_provider` | 404 | the account has no cabinet turned on | | `feature_disabled` | 403 | provider cabinets are temporarily switched off on the server | | `suspended` | 403 | the cabinet is suspended: messages and new links are not allowed | | `bad_request` | 400 | the body is malformed (`field` says which field) | | `bad_domain` | 400 | not a domain (an IP, no dot, invalid characters) | | `conflict` | 409 | already exists | | `not_found` | 404 | no such thing | | `domain_unverified` | 422 | the address isn't on your verified domain | | `bad_setting` | 422 | the key isn't in the settings list or the value doesn't fit (`key`) | | `limit_below_count` | 422 | the link's limit is below the number of its devices | | `limit` | 422 | a ceiling is reached: domains, links, keys, messages (`upgrade: true`: “Unlimited” lifts it) | | `billing_off` | 503 | payments for “Unlimited” are off on the server | | `prepaid_max` | 409 | “Unlimited” is already paid 12 months ahead | | `payment_unavailable` | 502 | the payment service did not answer, retry later | | `rate_limited` | 429 | too often, retry after `retry_after` | ## Limits | What | How many | | -------------------------------- | ---------------------------------- | | API keys | 10 | | domains | 50 | | limited links | 5000 | | limit of one link | 1000 devices | | devices in statistics | 500,000 | | messages to everyone / by system | 2 a day, at most once in 5 minutes | | messages to selected devices | 200 an hour, up to 20 devices each | | messages waiting for delivery | 500 | | API requests | 120 a minute | | manual domain checks | 20 an hour | Need more? [“Unlimited”](https://flowlock.cc/en/docs/limits.md) or FlowLock support. --- # Limits and “Unlimited” > How many domains, links, devices and messages the free cabinet allows, what “Unlimited” lifts for 1000 ₽ a month, and how to pay and renew. The provider cabinet is free, with limits. **“Unlimited”** lifts them: **1000 ₽ for 30 days**. ## Limits | What | Free | With “Unlimited” | | -------------------------------- | ---------------------------------- | ------------------------------------- | | domains | 50 | 1000 | | limited links | 5000 | 100,000 | | limit of one link | 1000 devices | 100,000 devices | | devices in statistics | 500,000 | 5,000,000 | | messages to everyone / by system | 2 a day, at most once in 5 minutes | 4 a day, at most once a minute | | messages to selected devices | 200 an hour, up to 20 devices each | 2000 an hour, up to 1000 devices each | | messages waiting for delivery | 500 | 5000 | | API requests | 120 a minute | 600 a minute | | API keys | 10 | 10 | | manual domain checks | 20 an hour | 20 an hour | “Unlimited” has ceilings too: they protect against abuse and are an order of magnitude above the free ones. The cabinet shows the limits in force on its “Unlimited” page. ## How to pay 1. Cabinet → “Unlimited” → “Buy for 1000 ₽ a month”. 2. The anore payment page opens: SBP, a card, YooMoney or crypto. The invoice is valid for 4 hours. 3. After paying you come back to the cabinet and see “Unlimited until …”. The payment usually arrives within seconds. If the cabinet still says it is waiting for the payment, come back later: it will not get lost. You can pay only in the cabinet on the website, signed in to your account. An API key can read the term and the payment history, but cannot pay. ## Renewing - **It is not a subscription**: nothing is charged by itself. - Renew any time with the same payment: 30 days are added to the current term. For example, paying 5 days before the end gives you 35 days from today. - You can pay at most 12 months ahead. - 3 days before the end an email goes to the account's address, and the cabinet shows a “renew” banner. ## When the term ends Nothing is deleted or switched off: domains, links (with their device limits) and messages keep working. But nothing new above the free limits can be created. The API then answers with `limit` or `rate_limited` and `"upgrade": true`, and the cabinet offers to renew. ## Also - The term belongs to the account, not to the cabinet: delete the cabinet and turn it on again, and the paid days stay. Deleting the account removes them. - Refunds go through FlowLock support, by hand. - The payment history is in the cabinet, on the “Unlimited” page. ## In the API ```sh # term, price, limits and an invoice still waiting for payment curl -s https://api.flowlock.cc/v1/provider/billing -H "Authorization: Bearer $FLOWLOCK_KEY" # payment history (newest first, 50 at a time) curl -s https://api.flowlock.cc/v1/provider/billing/payments -H "Authorization: Bearer $FLOWLOCK_KEY" ``` ```json { "available": true, "price_rub": 1000, "days": 30, "plan": { "name": "unlimited", "active": true, "paid_until": "2026-12-01T10:00:00Z", "days_left": 34, "renew_soon": false, "can_pay": true }, "pending": null, "limits": { "free": { "domains": 50, "…": 0 }, "unlimited": { "domains": 1000, "…": 0 } } } ``` `GET /v1/provider` carries `plan` too, and its `limits` are the ones in force now. Errors: `503 billing_off` (payments are off on the server), `409 prepaid_max` (paid 12 months ahead), `502 payment_unavailable` (the payment service did not answer). --- # Privacy: what the provider sees > What data about users the provider sees in the cabinet, what nobody sees, how long everything is kept, and how a user turns check-ins off. ## The provider sees - the device identifier: the HWID, only if the user turned on “Send HWID” or the subscription requires the HWID; otherwise an alias that stays the same for the pair “device + your cabinet” and is linked to nothing else; - the system and its version, the FlowLock version; - when the device first appeared and when it last checked in; - which [limited links](https://flowlock.cc/en/docs/install-links.md) it received; - what happened to [messages](https://flowlock.cc/en/docs/messages.md): received, shown, opened, done, declined. ## The provider doesn't see (and nobody does) The user's IP, country, sites, traffic, logs, their FlowLock account and email, other subscriptions, settings. ## FlowLock sees The same as the provider, plus the hash of the subscription domain. The IP is kept only in the server's memory, to protect against too frequent requests; it is never written to the database. The server never learns subscription domains that are in no cabinet: the apps send only the hash. ## The user decides FlowLock's settings have “Tell the provider I'm connected” (on by default). When it is off, the device doesn't appear in the statistics and receives no messages, and the subscription works as an ordinary one: no contacts, info block or settings from the provider. Settings changed by the provider are shown with the note “Set by the provider” and a “Restore mine” button. A data import always waits for the person's confirmation. ## How long data is kept - A device that stops checking in is deleted after 180 days. - Monthly statistics are kept for 24 months. - Messages and delivery results: 30 days after the message's delivery window ends. - Deleting the cabinet (or the account) deletes everything at once. --- # Installation > How to install FlowLock on macOS, Windows and Linux, what to do about the “unidentified developer” warning, and how updates arrive. FlowLock is a free client for the subscription you bought from a VPN provider. You can download it on the [“Downloads”](https://flowlock.cc/en/download/) page: the website offers the right file for your system. ## macOS You need macOS 14 or later; one build runs on both Apple Silicon and Intel. 1. Open the DMG and drag FlowLock to “Applications”. 2. FlowLock is signed without an Apple certificate, so macOS stops it on the first launch. Open “System Settings” → “Privacy & Security” and click “Open Anyway”. The same result with one command in Terminal: ```sh xattr -dr com.apple.quarantine /Applications/FlowLock.app ``` For TUN mode FlowLock asks for the administrator password once: it installs a small helper that starts the network adapter. ## Windows Two files to choose from: - **Installer** `…-Windows-x64-setup.exe`: the app goes to Program Files together with the “FlowLock VPN” service, so TUN mode works without extra prompts. Settings and subscriptions are kept when you uninstall. - **Portable version** `…-Windows-x64-portable.exe`: a single file, no installation. System proxy mode needs no administrator rights; when you choose TUN, FlowLock restarts with administrator rights and Windows asks for permission. The builds aren't signed with a Microsoft certificate, so SmartScreen may show a warning: “More info” → “Run anyway”. ## Linux You need Linux x64 with glibc 2.35 or later (Ubuntu 22.04, Debian 12, Fedora 36, Mint 21 and newer) and an X11 or Wayland desktop. **Installer**: the app goes to `/opt/flowlock`, with a menu entry and a systemd service: ```sh sudo sh FlowLock-*-Linux-x64-setup.run ``` To uninstall, run `sudo /opt/flowlock/uninstall.sh` (with `--purge` the settings are removed too). **Portable version**: a single file: ```sh chmod +x FlowLock-*-Linux-x64-portable && ./FlowLock-*-Linux-x64-portable ``` When you choose TUN, the system asks for the administrator password, and only the core restarts with those rights. The tray icon works in KDE, Cinnamon, Xfce, MATE and Budgie; GNOME needs the AppIndicator extension (it is turned on in Ubuntu). ## Updates FlowLock updates itself: it checks for new versions after launch and every few hours, and offers “Update and restart”. Before installing, it checks the file's signature and checksum. The channels are stable, beta and nightly; what's new in each build is shown on the [“Releases”](https://flowlock.cc/en/releases/) page. Next: [add a subscription](https://flowlock.cc/en/docs/subscriptions.md). --- # Subscriptions > How to add your provider's subscription to FlowLock, what the subscription card shows, HWID, and subscriptions from limited links. A subscription is the link your VPN provider gave you (usually `https://…` from their dashboard or bot). FlowLock downloads the servers, routing rules, traffic and expiry date from it by itself. ## Add a subscription - Copy the link and paste it into FlowLock: the add button in the subscriptions section, or “Add from clipboard” in the tray menu / menu bar. - Or open a `flowlock://add/…` link, if your provider put an “Add to FlowLock” button on their page: the app asks for confirmation. - Or open your provider's limited link `https://flowlock.cc/i/…`: the page opens FlowLock. FlowLock understands subscriptions from Remnawave, Marzban, 3x-ui and compatible panels: base64 and link lists, Xray JSON, sing-box JSON. Single servers (`vless://`, `hysteria2://`, `trojan://`, `ss://`, `vmess://`, WireGuard and AmneziaWG `.conf`, OpenVPN `.ovpn`) can be added the same way: they go to “My servers”. ## What a subscription shows - name, traffic and expiry, if the panel reports them (“unlimited”, “Expired”); - the “Support” and “Subscription page” buttons, and the provider's announcement; - for verified providers: their contacts, info block and renewal reminder. Subscriptions refresh by themselves (the panel suggests how often) and are downloaded directly, outside the VPN: many panels don't answer requests from VPN server addresses. ## HWID Many panels limit the number of devices by HWID. FlowLock sends it in the `x-hwid`, `x-device-os`, `x-ver-os`, `x-device-model` headers while “Send HWID” is on; for a single subscription the HWID can be set by hand. If the provider requires the HWID always, FlowLock says so: “required by the provider”. ## Subscription from a limited link A provider can give you a subscription link with a device limit. FlowLock adds such a subscription but doesn't show its address: it can't be copied or sent to a friend. On your second device add the same link, and it will take another place. ## Provider notifications The provider of a verified subscription can send a notification (for example, about maintenance) or ask the app to refresh the subscription. Import offers always wait for your “Add”, and settings changed by the provider are marked “Set by the provider” with a “Restore mine” button. All of this is turned off with the “Tell the provider I'm connected” setting. --- # Routes and custom databases > Routing modes, your own via VPN, direct and block rules, subscription rules, separate servers for sites, and custom geosite and geoip databases. ## Modes - **All via VPN.** - **Russian sites direct**: `.ru`, `.su`, `.рф` domains and Russian addresses bypass the VPN. - **Selective**: only what matches the rules goes through the VPN; everything else goes direct. ## Your own rules In the route editor each rule is a site, a link, an IP address or subnet, a `geosite:` / `geoip:` category, or `full:` (exact name), `keyword:` (part of a name) and `regexp:`. For each one you choose an action: via VPN, direct or block. ``` youtube.com geosite:telegram 1.2.3.0/24 full:api.example.com keyword:openai ``` Popular services (YouTube, Telegram, ChatGPT…) and “Blocked in Russia” can be added from ready-made sets, and many rules can be pasted as text. There is also “Block ads and trackers”. ## Subscription rules A provider can send its own rules (a Happ profile, Xray or sing-box JSON). They work together with yours, and yours win. A subscription refresh changes only the subscription's rules; yours stay. Any subscription rule can be turned off with a checkbox. ## A separate server for a site Sites and apps can be sent through a chosen server or group of servers: for example, YouTube through Poland and ChatGPT through the best-ping server in the Netherlands. The server can even come from another subscription. ## Custom geosite and geoip databases By default, `geosite:` and `geoip:` categories come from the SagerNet databases, and the ones missing there (`ru-blocked` and others) from runetfreedom. In routes (“geoip and geosite databases”) you can add your own, separately for sites and for IPs: - an Xray/v2ray `.dat` file **from a link** (for example, from the runetfreedom, Loyalsoldier or v2fly releases); - the same kind of file **from disk**; - a set of `.srs` files from a link template with `{name}`: `https://…/geosite-{name}.srs`. Your database comes first: anything it lacks is taken from the standard ones. Attributes work as in Xray: `geosite:google@cn`, `geosite:google@!cn`. A database link syncs between your devices, but a file from disk doesn't: on another device you have to choose it again. ## DNS DNS over DoH, a separate DNS for direct connections, and the IPv4/IPv6 choice are in the settings. --- # Apps and torrents > How to send a whole app through the VPN, directly or through a chosen server, and how to turn on “Torrents direct”. ## Apps In the “Apps” section (on macOS: “Settings” → “Routes” → “Apps”) a whole app can be: - sent through the VPN; - sent directly; - blocked; - or sent through a chosen server. You pick the app from the running ones or from the list of installed apps. On macOS the rule also catches the app's helper processes (for example, “Google Chrome Helper”). “Everything else direct” turns on selective mode: only the marked apps go through the VPN. > **In system proxy mode** a rule sees only the apps that use the proxy themselves. For rules to work for every app, > turn on [TUN](https://flowlock.cc/en/docs/modes.md). ## Torrents direct “Torrents direct” (off by default): recognised BitTorrent traffic and known torrent clients (qBittorrent, Transmission, µTorrent and others) bypass the VPN. This is faster and doesn't load the server, but trackers and peers see your real address. ## Rule order Torrents are checked first (if turned on), then apps and rules through other servers, then your rules, then the subscription's rules. --- # Themes and sharing them > Your own FlowLock colour theme: colours for the light and dark sides, how to share it as a link, QR code or file, and how to accept someone else's. In “Appearance” you can make **your own theme**: five colours (accent, background, cards, text, secondary text), each for the light and for the dark side, and a name of up to 40 characters. You can have several themes. ## Readability FlowLock checks contrast with the same rule as for provider themes: text at least 4.5:1 against the background, accent and secondary text at least 3:1. If a colour had to be adjusted, the editor says so, “The theme was adjusted for readability”, and shows the resulting colours. ## Sharing A theme has a link, a QR code and a `.flowlocktheme` file: ``` flowlock://theme/AR8fek1Mw4r09_UOFBH___8XIBsQIxrm7-lba2KTo5rQm9C10YE https://flowlock.cc/theme#AR8fek1Mw4r09_UOFBH___8XIBsQIxrm7-lba2KTo5rQm9C10YE ``` Both links carry the same thing. The colours and the name are written in the link itself, and the FlowLock server never sees them: in the web link they come after `#`, and the browser doesn't send that part. The web link is clickable in messengers: the website page shows a preview and an “Open in FlowLock” button. ## Accepting a theme Open the link or the file, or paste the link in “Appearance”. FlowLock shows a preview and asks for confirmation. A theme from a newer FlowLock version won't open until you update the app. ## Which theme applies Your own theme wins over the provider's (if you accepted it), and the provider's wins over the standard one. You choose the mode: system, light or dark. Your list of themes and the chosen theme sync through your [account](https://flowlock.cc/en/docs/account.md). --- # Account and sync > Why you might want a FlowLock account, and how sync, sign-in with a code, encryption, shared subscriptions and traffic statistics work. An account is optional: FlowLock works as usual without one. With an account you get sync between your devices, sign-in on a new device with a code, and shared subscriptions. ## Sign-in - Email and password. The password never goes to the server: the app derives your keys from it. - **With a code from another device**: on the new device FlowLock shows a code and a QR code. On a device where you are already signed in, open “Account” → “Link a device” and enter the code. No password is needed on the new device. - The device list, “Unlink”, and changing or resetting the password with a code sent by email are available in the app and on the [website](https://flowlock.cc/en/account/). ## Encryption - **Standard**: the vault key is stored on the server, wrapped with the server's key. The website can show and edit your subscriptions, and resetting the password loses nothing. - **End-to-end**: the key comes from your password, and the server holds only ciphertext. When you turn it on, you get a recovery code. Without it, a forgotten password means losing your synced data. ## Sync Subscriptions, your own servers, rules and settings travel between your devices. Changes arrive in about a minute while FlowLock is running. You can also sync through a folder (for example, on a cloud drive), with or without an account. A profile can also be exported to a file and loaded on another computer. You can add a subscription on the website too, under [“Subscriptions”](https://flowlock.cc/en/account/): the first device that starts up picks it up and adds it. ## Shared subscriptions The owner of a subscription can share it with friends without giving away the link: the FlowLock server downloads the subscription, and the friend gets only the servers, sealed with the key of their own account. The friend sees them marked “shared subscription from …”, with no links, addresses or export. The owner sends one-time invitations, sees the friends and can revoke access. ## Traffic statistics If you choose to (it is off by default), FlowLock sends daily totals to your account: connection time and traffic per device and per server, as plain numbers. Turn it off and the statistics are deleted from the server. Sync and shared subscriptions are being turned on gradually on the server. If you don't see them in the app, the feature isn't on for you yet. --- # TUN, system proxy and kill switch > How TUN and system proxy modes differ, why administrator rights are needed, how the kill switch works, and switching servers on the fly. ## Two modes - **TUN** (the default): FlowLock creates a network adapter, and all of the system's traffic goes through the VPN: browsers, games, the terminal, apps that can't use a proxy. Administrator rights are needed: on macOS once, for the helper; on Windows, the service from the installer or a restart of the portable version as administrator; on Linux, the service or a password through `pkexec`. - **System proxy**: FlowLock sets itself as the proxy in the system settings. No administrator rights are needed, but only apps that follow the system proxy go through the VPN. Command-line programs on Linux that read only `http_proxy` don't see it. The local proxy port is shown in the settings, so you can point an app at it by hand. The proxy can also be shared on your local network, with a username and password. ## Kill switch If the core crashes, FlowLock first tries to reconnect (up to 3 times in 2 minutes). In system proxy mode the kill switch keeps the proxy pointed at the crashed core: traffic is blocked instead of going around the VPN. You can lift it with the “Lift the block” button (in the window or in the tray menu); it is lifted by itself when you quit FlowLock. ## Switching on the fly You can change the server without reconnecting: open connections move to the new server right away. The “Auto: best ping” mode picks the fastest server by itself. ## Ping Ping can go through the server (HTTP: a request through the server itself), or use TCP or ICMP. TCP and ICMP go to the server directly, outside the VPN, so they show the delay to the server, not through the tunnel. --- # FAQ > Answers to common questions about FlowLock: where the servers come from, why macOS won't open the app, and what to do if a subscription doesn't load. ## Does FlowLock sell VPN? No. FlowLock is a client for the subscription you bought from a VPN provider. FlowLock has no servers of its own. ## macOS says FlowLock can't be opened FlowLock is signed without an Apple certificate. Open “System Settings” → “Privacy & Security” → “Open Anyway”, or run `xattr -dr com.apple.quarantine /Applications/FlowLock.app` (see [“Installation”](https://flowlock.cc/en/docs/install.md)). ## The subscription doesn't load - Check the link: open it in a browser. It should download text or JSON. - Some panels don't answer clients they don't know. In that case FlowLock retries the request with the v2rayN User-Agent by itself; if that doesn't help, set the subscription's User-Agent by hand (your provider will tell you which one). - The panel limits the number of devices by HWID: free up a slot in your provider's dashboard. ## “The subscription administrator has limited the number of devices” The subscription was added from a limited link, and all its places are taken. Contact your provider's support: their contacts are shown in the same window. ## Connected, but sites don't open - Try another server: switching works on the fly. - In system proxy mode not every app follows the proxy. Turn on TUN. - Check your rules: the site may have ended up in “direct” or “block”. ## What does FlowLock know about me? Without an account and without subscriptions that carry a provider ID, the app contacts the FlowLock server only for updates. A verified provider sees the device identifier, the system and the FlowLock version, but not your IP, sites or traffic (see [“Privacy”](https://flowlock.cc/en/docs/privacy.md)). Check-ins for the provider are turned off with the “Tell the provider I'm connected” setting. Diagnostics and traffic statistics are sent only if you turned them on. ## Where can I ask a question? On Telegram: [@FlowLock_bot](https://t.me/FlowLock_bot) for support, [@flowlock](https://t.me/flowlock) for news, [FlowLock InDev](https://t.me/FlowLockDev) for every new build.