Pricing API
Two public, read-only endpoints that let your website render your app's profile and live prices — no auth, no API key, CORS-enabled, callable straight from the browser. Every price carries a ready-made buy_url, so your pricing page and your Buy buttons stay correct the moment you edit a price on the dashboard.
Never hardcode prices
Render prices from this API instead of hardcoding amounts that drift the moment you change a price, and use the returned buy_url for your Buy buttons instead of assembling checkout URLs yourself.
App profile
GET https://www.usethatapp.com/api/v1/public/apps/{client_id}/client_id is your app's public OAuth client id, from the dashboard's Integration page — the same identifier your OIDC integration already uses.
{
"client_id": "AbC123dEf456...",
"name": "Acme Analytics",
"tagline": "Dashboards your team actually reads",
"listing_mode": "external",
"url": "https://acmeanalytics.com",
"marketplace_url": "https://www.usethatapp.com/apps/acme-analytics/"
}listing_mode is "marketplace" (the app has a full product page on usethatapp.com) or "external" (the app still appears in UseThatApp search, but its card links out to your own registered website). You can change it from the dashboard or via the MCP update_app_listing tool — see MCP Server.
Prices
GET https://www.usethatapp.com/api/v1/public/apps/{client_id}/prices/{
"client_id": "AbC123dEf456...",
"app_name": "Acme Analytics",
"has_free_tier": true,
"prices": [
{
"public_id": "prc_9f2kq8w7",
"product_id": "prod_9XkKe2QGxN4Ttz1Rw7Ya",
"product_name": "Pro",
"amount": "10.00",
"currency": "usd",
"is_recurring": true,
"frequency": "month",
"buy_url": "https://www.usethatapp.com/buy/prc_9f2kq8w7/"
},
{
"public_id": "prc_x4n7d2mk",
"product_id": "prod_Vt3mPa8LqZc5Ryw2Kd0B",
"product_name": "Lifetime",
"amount": "199.00",
"currency": "usd",
"is_recurring": false,
"frequency": null,
"buy_url": "https://www.usethatapp.com/buy/prc_x4n7d2mk/"
}
]
}| Field | Meaning |
|---|---|
public_id | Opaque price identifier (prefix prc_) — the id inside buy links. |
product_id | The product this price belongs to (prod_…). Matches product_public_id from the entitlement endpoint, so gate your features on it — the plan bought is the plan you unlock. (The entitlement's own product_id carries the same value — the fields are equal-valued aliases.) See Licensing. |
amount / currency | Decimal string (e.g. "10.00") and lowercase ISO currency code (e.g. "usd"). |
is_recurring / frequency | Billing interval for recurring prices: "day", "week", "month", or "year"; frequency is null for one-time prices. |
buy_url | Ready-made hosted checkout link for this price — use it as your Buy button's href. |
has_free_tier | True when the app offers a free product. Free tiers have no price rows, so render your "Free" column from this flag. |
Call it with the SDK
On a server, prefer the SDK — it wraps both endpoints with typed results (AppInfo, AppPrices with Price / UtaPrice entries) and needs only UTA_CLIENT_ID, no OAuth secrets:
Python
from usethatapp import get_app_info, get_prices
info = get_app_info() # AppInfo(name, tagline, listing_mode, ...)
plans = get_prices() # AppPrices(..., has_free_tier, prices)
for p in plans.prices:
render_plan(p) # p.buy_url is your Buy button href
# async variants: get_app_info_async(), get_prices_async()JavaScript
import { getAppInfo, getPrices } from "usethatapp";
const info = await getAppInfo(); // { name, tagline, listing_mode, ... }
const { prices, has_free_tier } = await getPrices();
for (const p of prices) {
renderPlan(p); // p.buy_url is your Buy button href
}Error mapping: 404 raises a plain UtaError (app unknown, unpublished, or external sales not enabled yet); 429 and 5xx raise UtaServerError (retriable). See Error Handling.
Call it from the browser
Because the endpoints are CORS-enabled, a static marketing page with no server at all can fetch them directly:
const CLIENT_ID = "<your-client-id>";
const res = await fetch(
`https://www.usethatapp.com/api/v1/public/apps/${CLIENT_ID}/prices/`
);
const { prices, has_free_tier } = await res.json();
// render prices → each price's buy_url is your Buy button hrefBehavior notes
- Visibility: both endpoints only resolve for published apps with external sales enabled — anything else is a 404 (indistinguishable from an unknown
client_id). - Caching: responses send
Cache-Control: public, max-age=60— prices can change, so the public cache is kept short. - Rate limit: 120 requests/minute per IP; excess requests get 429.
- CORS:
Access-Control-Allow-Origin: *— call it from any origin, no proxy needed. - Auth: none. Everything here is public data; there are no secrets to leak from a browser call.
Next steps
See the full funnel in Sell from your own website, the link parameters in Purchase links, and the rest of the HTTP surface in the REST API reference.
