# Backend contract The admin UI is a single `backend/admin.html` file. It sends the configured admin Bearer token in memory/session storage and calls only `/admin/api/*` endpoints. ## Device flow 1. Operator creates a user and device in the page. 2. Backend returns a one-time `enrollment_url` and a stable `subscription_url`. 3. The app makes the first request with `X-Device-Token: ` and `User-Agent: vpnapp/vMAJOR.MINOR/DEVICE_UUID`. 4. Backend checks URL UUID, credential, and User-Agent UUID atomically, records the User-Agent, and returns the user's decrypted-for-transport config payload. 5. Polling every few hours uses the same device token and bound User-Agent. A different installation cannot reuse the same device binding unless the token is copied; UUID and User-Agent alone never authenticate. The device endpoint must be deployed behind TLS. The admin token is not accepted on `/d/{device_id}`. Server configs and user secrets are Fernet-encrypted at rest with `VPNAPP_SECRET_KEY`; only sanitized fields are shown in the admin list. The reusable client-side request code is in `app/services/subscription.py`. It accepts an injected secret store, emits the required User-Agent, performs one-time enrollment, refreshes the device subscription asynchronously, and maps the response into the separate VLESS/Amnezia/FreeTurn profile models. Android should connect its injected store to Keystore-backed native storage before shipping credentials.