Hosting Provider
Selling through UseThatApp means buyers finish hosted checkout and land back in your deployed app, where the usethatapp SDK — a confidential, server-side client — verifies what they bought. This page covers what your hosting provider needs to make that work: a safe place to keep your client secret, plus a public HTTPS callback URL if you use the Hosted sign-in add-on (license-key verification needs no callback at all).
Hosting a separate marketing site? The purchase surface needs none of the secrets on this page: purchase_url / purchaseUrl is a pure URL builder, manage_url / manageUrl and get_prices / getPrices need only UTA_CLIENT_ID, and the Pricing API is public and CORS-enabled — a static pricing page can fetch it straight from the browser. Only the app itself (the OIDC client) needs the setup below.
Overview
You need two things at runtime: a public HTTPS callback your app exposes, and your OAuth client credentials kept on the server.
Public Callback URL
An HTTPS route on your app (your UTA_REDIRECT_URI) that UseThatApp redirects back to after sign-in. You register it on the dashboard's Integration page, where it's matched exactly.
Your Client Secret
The UTA_CLIENT_SECRET for your OAuth client. The SDK uses it to exchange the authorization code for tokens. Store it as a server-side secret — never in code, version control, or anything that reaches the browser.
The Sign-In Flow
The diagram below shows the authorization-code flow. The browser is redirected between your app and usethatapp.com; the code-for-tokens exchange happens server-to-server using your client secret.
┌────────────┐ ┌────────────────────┐ ┌──────────────────────────┐
│ Browser │ │ usethatapp.com │ │ Your Hosting Provider │
│ │ │ (OpenID Provider)│ │ │
│ GET │──1───▶│ /login → │ │ │
│ /login │ │ begin_login() │ │ ┌────────────────────┐ │
│ │◀──2───│ redirect to │◀──────│ │ GET /login │ │
│ │ │ authorize │ │ │ begin_login() │ │
│ sign in │──3───▶│ user authenticates│ │ └────────────────────┘ │
│ │◀──4───│ redirect back │ │ ┌────────────────────┐ │
│ GET │───────────────────5───────────────▶│ │ GET /callback │ │
│ /callback │ │ │ │ │ complete_login() │ │
│ │ │ /token (exchange │◀──6───│ │ exchange code │ │
│ │ │ code → tokens) │───7──▶│ │ → UtaSession │ │
└────────────┘ └────────────────────┘ │ └─────────┬──────────┘ │
│ ┌────────▼───────────┐ │
┌────────────────────┐ │ │ get_entitlement( │ │
│ entitlement API │◀──8───│ │ access_token) │ │
│ (Bearer token) │───9──▶│ │ → live plan │ │
└────────────────────┘ │ └────────────────────┘ │
│ ┌────────────────────┐ │
│ │ UTA_CLIENT_SECRET │ │
│ │ (env var / secret) │ │
│ └────────────────────┘ │
└──────────────────────────┘Step 1 — Get Your Credentials
Open your app's Integration page on the usethatapp.com dashboard and collect:
Client ID
Your app's OAuth client id. You'll set this as the UTA_CLIENT_ID environment variable. It identifies your app — there's no separate app id.
Client Secret
Shown once when you create or rotate it, then stored hashed. You'll set it as UTA_CLIENT_SECRET. Never commit it — treat it like a database password, and keep it off the browser.
Redirect & Post-Logout URLs
Register your production callback (your UTA_REDIRECT_URI) and any post-logout return URLs. Both are exact-match allow-lists — the URL your app sends must appear verbatim, HTTPS, on your domain.
Login URL
The page in your deployed app that starts sign-in. Buyers returning from hosted checkout land here by default (as do marketplace launches), so it must be live on your production host before you turn on buy links. The same domain rule applies to any next URLs on your purchase and manage links: HTTPS, on your registered domain.
Step 2 — Set Your Environment Variables
Set the three required values; the rest default to production. Only the client secret is sensitive — store it through your provider's secret store, not a plain env var, where you can.
UTA_CLIENT_ID=... # required
UTA_CLIENT_SECRET=... # required (server-side secret)
UTA_REDIRECT_URI=https://yourapp.com/callback # required, registered on the dashboard
# optional — default to production:
UTA_ISSUER=https://www.usethatapp.com/o
UTA_API_URL=https://www.usethatapp.com
UTA_SCOPES="openid entitlements"Mounted-File Secret (Secret Files)
If your provider mounts secrets as files (Render Secret Files, Fly.io volumes, Kubernetes secret volumes, GCP Secret Manager volume mounts, AWS App Runner secret files), set UTA_CLIENT_SECRET_PATH instead of UTA_CLIENT_SECRET — the SDK reads the secret from the file.
UTA_CLIENT_ID=...
UTA_REDIRECT_URI=https://yourapp.com/callback
UTA_CLIENT_SECRET_PATH=/etc/secrets/uta_client_secretWhere to Store the Secret by Provider
Use whichever your provider offers — they're purpose-built for sensitive material and rotate, audit, and encrypt it for you. The right column shows the recommended UseThatApp env var:
- Render — Secret Files →
UTA_CLIENT_SECRET_PATH=/etc/secrets/uta_client_secret - Railway — Shared Variables →
UTA_CLIENT_SECRET - Fly.io —
fly secrets set UTA_CLIENT_SECRET=...(or mount a volume and useUTA_CLIENT_SECRET_PATH) - AWS — Secrets Manager / SSM Parameter Store → fetch at boot into
UTA_CLIENT_SECRET, or App Runner secret files →UTA_CLIENT_SECRET_PATH - Google Cloud — Secret Manager volume mount →
UTA_CLIENT_SECRET_PATH - Azure — Key Vault references in App Service →
UTA_CLIENT_SECRET - Kubernetes — Secret mounted as a volume →
UTA_CLIENT_SECRET_PATH - Vercel / Netlify — Encrypted Environment Variables →
UTA_CLIENT_SECRET
⚠ Security note: The client secret must never reach the browser. Run the SDK server-side; a single-page app should call a small backend-for-frontend rather than the SDK directly. If the secret is ever committed or exposed, rotate it from the UseThatApp dashboard immediately.
Step 3 — Expose Your Callback URL
Your app must expose the HTTPS route named in UTA_REDIRECT_URI (e.g. /callback) so UseThatApp can redirect the user back to it after sign-in. Once your app is deployed and reachable, register that exact URL on your dashboard. Requirements:
- HTTPS on your app's domain (
localhostallowed for development). - Exact match — the registered URL and
UTA_REDIRECT_URImust be byte-for-byte identical. - Publicly reachable — no IP allowlists or VPN-only endpoints.
Popular Hosting Providers
UseThatApp works with any provider that can run a Python or Node.js backend on a public HTTPS URL and inject a server-side secret.
Railway
Deploy from GitHub with zero config. Supports Python & Node.js. Shared Variables for the client secret.
Render
Free tier available. Automatic deploys from Git. Environment variables and Secret Files built in.
Fly.io
Run containers close to your users. fly secrets set keeps UTA_CLIENT_SECRET encrypted at rest.
DigitalOcean App Platform
Managed platform with Git-based deploys. Encrypted environment variables out of the box.
Heroku
Classic platform-as-a-service. Store the client secret as a Config Var.
AWS
EC2, App Runner, or Elastic Beanstalk. Store UTA_CLIENT_SECRET in Secrets Manager and inject at boot.
Google Cloud Run
Serverless containers. Bind UTA_CLIENT_SECRET directly from Google Secret Manager.
Azure App Service
Microsoft's PaaS for web apps. Reference Azure Key Vault from app settings.
Vercel
Great for Next.js — store UTA_CLIENT_SECRET as an encrypted environment variable per environment.
Next Steps
Once your environment variables are in place and your callback URL is registered and reachable, head to the framework guide for your stack to wire up the login and callback routes:
