One API foundation, two surfaces
Customer-facing partner operations and administrative infrastructure operations are deliberately separate. Partners and developers work with the customer surface; administration is never exposed through public or client-side code.

Partner API surface
Endpoints below are implemented as FlowMoney VPN backend services. Each row maps to our public API contract (/api/v1/…), which the gateway will expose under flowmoneyvpn.com once the domain is connected; until then the deployed function routes are authoritative and are served exclusively over HTTPS.
| Method | Path | Required scope | Status | Purpose |
|---|---|---|---|---|
| POST | /functions/partnerToken | — | Implemented | Client-credential or authorization-code (PKCE) exchange for a short-lived scoped bearer token. Contract path: POST /api/v1/partner/token. |
| GET | /functions/partnerApi?action=status | — | Implemented | Partner name, authorization status, environment, scopes and rate budget. Contract path: GET /api/v1/partner/status. |
| GET | /functions/partnerApi?action=locations | vpn.locations.read | Implemented | Available exit locations from the live server registry. Contract path: GET /api/v1/vpn/locations. |
| GET | /functions/partnerApi?action=servers | vpn.locations.read | Implemented | Server availability summary. Hostnames, addresses and key material are never exposed. Contract path: GET /api/v1/vpn/servers. |
| GET | /functions/partnerApi?action=availability | vpn.locations.read | Implemented | Honest availability for a country, region, city or postal query — never fabricated. Contract path: GET /api/v1/vpn/availability. |
| POST | /functions/partnerApi?action=customer-link | vpn.customer.link | Implemented | Single-use, short-lived account-linking request that returns the customer consent URL. Contract path: POST /api/v1/partner/customer-link. |
| GET | /functions/partnerApi?action=entitlement | vpn.entitlement.read | Implemented | Confirm a customer’s subscription entitlement, for a consented customer only. Contract path: GET /api/v1/partner/entitlements. |
| POST | /functions/partnerApi?action=session | vpn.connection.read | Implemented | Record a VPN session for a consented customer with an active entitlement. Contract path: POST /api/v1/partner/session. |
| POST | /functions/partnerApi?action=session-revoke | vpn.connection.read | Implemented | Revoke the customer’s active session. Contract path: POST /api/v1/partner/session/revoke. |
| GET | /functions/partnerApi?action=connection | vpn.connection.read | Implemented | Authorised connection status for the consented customer. |
| GET | /functions/partnerApi?action=profile | — | Implemented | Returns the calling partner, its granted scopes and remaining rate budget. |
| GET | /authorize | — | Implemented | Customer consent screen for delegated authorisation (PKCE) and account linking. |
| POST | /functions/partnerAdmin | — | Admin only | Partner registration, credential issue, rotation and revocation. Never available to partners. |
Server-to-server authentication
Partners authenticate with a client identifier and secret over TLS. Secrets are generated server-side, stored only as salted hashes, and can be rotated or revoked instantly.
POST /functions/partnerToken
Content-Type: application/json
{
"grant_type": "client_credentials",
"client_id": "fmvpn_partner_9c1a…",
"client_secret": "…"
}
200 OK
{
"access_token": "fmv_8f3c…",
"token_type": "Bearer",
"expires_in": 3600,
"scopes": ["vpn.locations.read", "vpn.entitlement.read"]
}Delegated customer authorisation
OAuth-style authorisation code flow with PKCE. Tokens are short-lived, scoped and bound to one customer consent — the model FM Kinetic Wallet will use.
1. Redirect the customer to:
/authorize?client_id=…&redirect_uri=…&scope=vpn.entitlement.read
&state=…&code_challenge=…&code_challenge_method=S256
2. The customer consents inside FlowMoney VPN.
3. Exchange the returned code (server-to-server):
{ "grant_type": "authorization_code", "code": "…",
"code_verifier": "…", "client_id": "…",
"client_secret": "…", "redirect_uri": "…" }
→ scoped token bound to that single customerLeast privilege by default
Rate limits and error handling
- 120 requests per minute per credential. Exceeding it returns 429 with a retry hint.
- Errors return { "error": "code", "message": "…" } with a matching HTTP status.
- Expired or revoked tokens return 401 immediately; re-authenticate rather than retrying.
- Every request is written to the audit trail with the client identifier, action and outcome.
- Token lifetime is one hour; authorization codes are single-use and expire in minutes.
Where the encrypted tunnel actually lives
A website cannot create a system-wide VPN tunnel. The platform supplies identity, location selection, entitlement and peer provisioning; our native clients build and maintain the WireGuard tunnel on the device.
Android
WireGuard userspace tunnel inside a VpnService foreground service.
Key pair generated on device; public key registered with the control plane.
Specification · in development
iPhone & iPad
NetworkExtension packet tunnel provider with the WireGuard tunnel implementation.
Configuration delivered as a signed, short-lived peer profile.
Specification · in development
Windows
WireGuardNT tunnel service driven by the desktop client.
Service handles the tunnel; the UI never stores the private key.
Specification · in development
macOS
NetworkExtension system extension using the WireGuard framework.
Menu-bar control, automatic re-connect and revocation on sign-out.
Specification · in development
Administrative infrastructure operations — server registration, capacity, health, credential management and provisioning authorisation — live behind administrator authentication in the FlowMoney VPN administration centre. They are not exposed to partners, to customers, or to public frontend code.
Build on FlowMoney VPN
Register your application, request the scopes you need, and test against our sandbox environment once credentials are issued.
