Soar API Setup
Connect Kotlin to a conforming Unified Platform host: client build, host environment, sessions, and verification.
This is the Unified Mode counterpart to Supabase Setup: everything needed to run the Android app against a conforming Web host instead of a Supabase project. If you haven't picked a mode yet, start at Backend Modes.
No host is privileged by framework name — Next.js, Nuxt, and TanStack Start all work; conformance to the frozen contracts is the compatibility boundary.
1. Deploy a conforming host
Deploy one of the Web templates as a Unified Platform Host and complete its host-side setup (database, Better Auth URL and secret, App API):
Sign up on the Web and verify /api/auth/get-session works before touching the
Android side. For the cross-template picture, see the
platform Unified Quick Start.
2. Configure the client build
Unified Mode needs three keys in local.properties:
# local.properties
SOAR_BACKEND_MODE=soarApi
# Service root of the host deployment. Do NOT include /api/app/v1 — the client
# appends it. Release builds require HTTPS; from the Android emulator the host
# machine is 10.0.2.2 (not localhost), e.g. http://10.0.2.2:3000
SOAR_API_BASE_URL=https://your-web-app.example.com
# Native origin sent on Better Auth requests: a bare scheme ending in `://`.
# Must match the host's APP_SCHEME / trustedOrigins allow-list. It also
# generates the app's deep-link scheme in AndroidManifest.xml.
SOAR_API_ORIGIN=soar://The SUPABASE_* keys can stay unset — the Supabase client is never built in
this mode. Google Sign-In still uses Credential Manager on device in both
modes; the audience is validated server-side (next step).
Configuration errors stop this build. A missing or malformed SOAR_API_*
value fails startup with a diagnosable error — there is no silent Supabase
fallback.
3. Configure the host for this app
On the server (the selected host's deployment environment), the app expects the native support described in Native Authentication:
| Server variable | Why the Android app needs it |
|---|---|
APP_SCHEME=soar:// | The app sends Origin: soar:// on every request; Better Auth rejects untrusted origins with 403. Must equal the client's SOAR_API_ORIGIN. |
GOOGLE_ANDROID_CLIENT_ID | Audience allow-list entry for native Google ID-token sign-in via Credential Manager. |
REVENUECAT_WEBHOOK_AUTHORIZATION + REVENUECAT_PRODUCT_* | Syncs Google Play purchases into the shared subscription row. |
STORAGE_PROVIDER (+ R2_* in production) | Presigned-upload object storage backing the uploads repository. |
4. Sessions live in the Android Keystore
In Unified Mode the app authenticates with Better Auth Bearer tokens (the
set-auth-token response header), not cookies:
- The token is persisted only in the Keystore-backed secure store
(
SecureTokenStore) — never logged and excluded from backups. - On relaunch the stored session is restored and validated against the server; sign-out clears both the stored token and in-memory state.
- Whenever a response carries a new
set-auth-token, the stored token is replaced. - Sessions are database-backed and revocable: revoking a session on the web
invalidates the Android token immediately, and the app treats
401as "sign in again" — it never retry-loops and never falls back to Supabase auth.
5. RevenueCat appUserID
The purchases layer always logs in to RevenueCat with the current user's ID —
in Unified Mode that is the Better Auth user ID. This is what lets the server's
RevenueCat webhook resolve app_user_id
back to the same Better Auth user and update the one shared subscription
row that the web reads too.
Keep RevenueCat's Restore Behavior set to Transfer disabled: a receipt already attached to another account should surface a support-facing error, not silently move entitlements between users.
6. Push notifications
Unified Android registers FCM tokens through the device-token endpoints. The frozen v1 test-push endpoint is APNs-only, so the app reports test sending as unsupported instead of calling it — real FCM delivery is unaffected.
Verify the setup
Run the shared smoke test across both surfaces:
- Sign up or sign in on Android (email and Google), then open the same account on the Web.
- Update the profile on one surface and read it from the other.
- Create, edit, reorder, and delete a todo across both surfaces.
- Upload an avatar and confirm its completion URL is readable.
- Revoke the Android session from the Web and verify the app returns to sign-in.
- After a sandbox purchase, confirm the same entitlement appears on both surfaces.
- Register the FCM device token and confirm it appears in the host's token registry.
For a concrete end-to-end walkthrough of one host-and-client pair, follow Next.js + Swift Unified Setup — the steps map one-to-one onto Android.
Related pages
Backend Modes
The decision page: comparison, mode resolution, and what does not mix.
Configuration
Every build key, including SOAR_BACKEND_MODE and SOAR_API_*.
Native Authentication
Bearer sessions, email OTP, Google ID-token sign-in.
Next.js + Swift Unified Setup
One concrete host-and-client example; steps map onto Android.
