Python SDK for usethatapp.com — verify launch envelopes and query user license tiers.
Project description
usethatapp
Python SDK for usethatapp.com. Verifies the encrypted+signed launch envelope the marketplace POSTs to your app and lets you pull the user's current license tier on demand.
Framework-agnostic. Use with Django, Flask, FastAPI, Starlette,
Dash, Streamlit, Pyramid, Bottle, AIOHTTP, plain WSGI, or a CLI. The
only runtime dependencies are cryptography and httpx. A Django
helper is shipped, but only imported when Django is installed.
v1.0 is a breaking rewrite. The old browser-side
usethatapp.js/requestAccessLevel()/ iframe handshake has been removed. See CHANGELOG.md for migration notes.
How it works
usethatapp.com uses a two-phase, license-centric handoff:
- Launch (one-way push). When a user clicks Launch app on
usethatapp.com, the marketplace POSTs an encrypted+signed envelope
to your app's URL. The envelope carries an opaque
user_key. Your app verifies + decrypts it, persistsuser_keyagainst its own session, and renders your UI. - Query (server-to-server pull). Whenever your app needs the
user's current license tier, it POSTs a signed request to
https://usethatapp.com/licensing/getversion/with theuser_keyand gets back the live product name (ornull).
Install
pip install usethatapp
Requires Python 3.9+. Runtime deps: cryptography, httpx. No web
framework required.
Settings
The SDK reads from django.conf.settings only if Django is
installed and configured; otherwise it falls back to environment
variables. Non-Django users just export these:
| Name | Required | Purpose |
|---|---|---|
UTA_APP_ID |
yes | Your app's UUID on usethatapp.com. |
UTA_PRIVATE_KEY |
yes† | Your RSA-2048 private key (PEM string or RSAPrivateKey object). |
UTA_PRIVATE_KEY_PATH |
yes† | Filesystem path to a PEM file containing the private key. †Set this or UTA_PRIVATE_KEY. |
UTA_MARKET_PUBLIC_KEY |
yes* | Marketplace public key (PEM string or RSAPublicKey). *A production default is bundled. |
UTA_MARKET_PUBLIC_KEY_PATH |
no | Filesystem path to a PEM file containing the marketplace public key (alternative to UTA_MARKET_PUBLIC_KEY). |
UTA_API_URL |
no | Defaults to https://usethatapp.com. |
UTA_CLOCK_SKEW_SECONDS |
no | Defaults to 60. |
UTA_REQUEST_TIMEOUT_SECONDS |
no | Defaults to 10. |
The *_PATH variants are intended for hosting providers that mount
secret files into the container (Render Secret Files, Fly.io volumes,
Kubernetes secret volumes, GCP Secret Manager volume mounts, etc.).
The SDK reads the file at boot. If both the direct setting and the
path setting are provided for the same key, the direct value wins.
Public API
Three functions cover every integration:
from usethatapp import (
get_user, # framework-agnostic: takes the raw uta_payload str/dict
get_user_from_request, # auto-detects Django / Flask / Werkzeug requests
get_user_from_request_async, # for Starlette / FastAPI (await)
get_version, # signed server-to-server license-tier lookup
get_version_async, # async variant
UtaUser, # frozen dataclass: user_key, app_id, iat, exp, version_hint
# typed errors:
UtaError, UtaSignatureError, UtaPayloadExpiredError,
UtaAppMismatchError, UtaBadRequestError, UtaSessionRevokedError,
UtaUnknownSessionError, UtaServerError, UtaConfigError,
# Django-only (imported lazily — present only if Django is installed):
uta_launch_view,
)
UtaUser carries only the opaque user_key — no PII. Persist it
against your own session; pass it to get_version whenever you need
the live license tier.
Quickstart — any framework
from usethatapp import get_user, get_version, UtaError
# In your POST handler — however your framework spells it:
raw_payload = read_form_field("uta_payload") # str
try:
uta_user = get_user(raw_payload)
except UtaError as e:
return bad_request(str(e))
save_to_session("uta_user_key", uta_user.user_key)
# Later, anywhere in your app:
version = get_version(load_from_session("uta_user_key")) # str | None
Framework examples
Runnable single-file examples for each major framework live under
examples/:
examples/django_min/—@uta_launch_viewexamples/flask_min/—get_user_from_request(request)examples/fastapi_min/—await get_user_from_request_async(request)examples/dash_min/— Flask route on Dash's underlying serverexamples/streamlit_min/— sidecar pattern +get_user
uta_user.version_hintis not the source of truth. Use it only for first paint. The authoritative value comes fromget_version(user_key).
Error mapping
get_version maps server status codes to typed exceptions:
| Status | Exception | Meaning |
|---|---|---|
| 400 | UtaBadRequestError |
Bad JSON / ts outside window / replay. |
| 401 | UtaSignatureError |
Signature verification failed. |
| 403 | UtaSessionRevokedError |
Treat as "user logged out". |
| 404 | UtaUnknownSessionError |
Unknown user_key or app_id. |
| 5xx | UtaServerError |
Retriable with backoff. |
All inherit from UtaError — catch that for a single except clause.
License
MIT — see LICENSE.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file usethatapp-1.0.0.tar.gz.
File metadata
- Download URL: usethatapp-1.0.0.tar.gz
- Upload date:
- Size: 26.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.8
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
71cc887e24663ed43433952a5ef93b39a291900d2662ff9bff8e6b077841a265
|
|
| MD5 |
9a360d15054bf638c87818a211ad86bf
|
|
| BLAKE2b-256 |
aa1f80c91d2d2ce2c35ee11937d3d8c98c449baedcbc560d45d5e53e38df85a4
|
File details
Details for the file usethatapp-1.0.0-py3-none-any.whl.
File metadata
- Download URL: usethatapp-1.0.0-py3-none-any.whl
- Upload date:
- Size: 17.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.8
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
86b787faa5bd95f73104abefef188c2c12bd4a88a03d6d73dd8b0402da3ac7ab
|
|
| MD5 |
19b3d5a4538ddb3d52cea909b175175b
|
|
| BLAKE2b-256 |
9fda81f54bc3da85788b4a3f5b58784847f5c8bb8c83abb87703ef48d559d00e
|