UseThatApp Documentation
Sell your web app from your own website — UseThatApp is the merchant of record. Put live prices and Buy buttons on your site; UseThatApp runs the hosted checkout, processes payment, calculates and remits tax, and handles refunds and chargebacks. The buyer lands back in your app with their purchase live — the license is created during checkout, no webhooks — and you get payouts via Stripe. Your app verifies each purchase with a license key — or lets UseThatApp run sign-in — through one SDK: usethatapp on PyPI and npm.
Reading this as an AI agent?
Every page on this site is fully pre-rendered static HTML — no JavaScript needed. For the fastest path, fetch docs.usethatapp.com/llms.txt (an index of all pages with summaries and integration rules) or docs.usethatapp.com/llms-full.txt (the entire site as one Markdown file — no crawling required). Page URLs are extensionless routes; the same list is in sitemap.xml.
One Merchant of Record, Two Ways to Verify
Merchant of record
The service everything else hangs off. Hosted buy links and a live pricing API; we take the payment, remit the tax, handle refunds and chargebacks, and pay you via Stripe.
License keys
Verify purchases while keeping your own auth. Every purchase mints a key your server validates in one call — included in the per-sale fee, no login of ours involved.
Hosted sign-in
Or let us run login: buyers return from checkout already signed in, and the same session answers what they bought. An optional add-on, free for an introductory period.
The Loop
Everything in these docs serves one journey — a visitor on your website becoming a paying user of your app:
- Live prices on your site. Your pricing page renders from the Pricing API (
get_prices/getPrices, or plain fetch — it's public and CORS-enabled). Never hardcode a price. - Buy button → hosted checkout. Each price carries a ready-made
buy_url(or build one withpurchase_url/purchaseUrl). UseThatApp runs checkout as the merchant of record. - Back into your app. The license is created synchronously during checkout, so what they bought is live the moment they land — no webhooks, no polling.
- Verify, whichever way suits your app. Keeping your own accounts? The return carries a
uta_orderref you exchange for a license key, thenvalidate_license_key/validateLicenseKeyis your gate. Rather we ran login? Sign in with UseThatApp returns them signed in andget_entitlementanswers from that session. Either way, branch on the stableproduct_public_id. - Manage and upgrade. Deep-link "Manage subscription" with
manage_url/manageUrl; upsell with another purchase link.
Your app's marketplace listing on usethatapp.com is a complementary discovery channel — in external listing mode its card links straight out to your own site. Purchases are open to buyers in the US, the EU, Canada, Australia and more; sellers must be based in the United States.
Quick Example
Live prices on your page, then gate what the buyer bought — shown here in Hosted sign-in mode (keys mode swaps the gate for validate_license_key, see License Keys). The usethatapp SDK (PyPI / npm) is a confidential, server-side client — it holds your client secret and never runs in the browser:
Python
from usethatapp import get_entitlement, get_prices, purchase_url
# Your pricing page — live prices, never hardcoded:
prices = get_prices() # AppPrices(..., prices=(Price(...), ...))
for p in prices.prices:
show_plan(p.product_name, p.amount, p.currency, p.buy_url)
# Your gate, Hosted sign-in mode (keys mode: validate_license_key):
ent = get_entitlement(session["uta_access_token"])
if ent.entitled and ent.product_public_id == "prod_<your-pro-id>":
... # serve paid content
else:
offer_upgrade(purchase_url("<prc-price-id>"))JavaScript
import { getEntitlement, getPrices, purchaseUrl } from "usethatapp";
// Your pricing page — live prices, never hardcoded:
const { prices } = await getPrices();
prices.forEach((p) =>
showPlan(p.product_name, p.amount, p.currency, p.buy_url));
// Your gate, Hosted sign-in mode (keys mode: validateLicenseKey):
const ent = await getEntitlement(req.session.utaAccessToken);
if (ent.entitled && ent.product_public_id === "prod_<your-pro-id>") {
// serve paid content
} else {
offerUpgrade(purchaseUrl("<prc-price-id>"));
}Hosted sign-in itself is two small routes (/login and /callback) — the Quick Start walks that whole loop end to end; keys mode skips both.
Supported Frameworks
Choose your language to see the full list of framework guides, or jump straight to the Quick Start.
