Product types, apps, tags, causes, domain routes for events and tournaments, and the small lookup endpoints.
Mostly reads, mostly cacheable. The catalog endpoints describe what the protocol offers; the
lookup endpoints return small enumerations your UI needs at render time.
One of these is load-bearing rather than incidental: /api/apps/{id}/config is the single
source of truth for whether signup requires an invite. Read it rather than mirroring the answer
into your own environment, which is how the two get out of sync.
Create a product type. Needs MANAGE_PRODUCT_TYPES.
DELETE
/api/product-types/{slug}
app key + user, entitlement
Delete one. Needs MANAGE_PRODUCT_TYPES.
GET
/api/product-types/{slug}
app key
One product type.
PATCH
/api/product-types/{slug}
app key + user, entitlement
Update one. Needs MANAGE_PRODUCT_TYPES.
GET
/api/apps
app key
The app catalog: active apps by default (activeOnly=false for all), with publicOnly, layer (protocol or client) and contentType filters. Each row carries accessPolicy and catalogTease.
POST
/api/apps
app key + user, entitlement
Register an app. Operator route: needs MANAGE_ACCOUNTS.
DELETE
/api/apps/{id}
app key + user, entitlement
Delete an app. Needs MANAGE_ACCOUNTS.
GET
/api/apps/{id}
app key + user, entitlement
One app, the full record. Needs MANAGE_ACCOUNTS; a client app reads /config and /access instead.
PUT
/api/apps/{id}
app key + user, entitlement
Update an app. Needs MANAGE_ACCOUNTS.
GET
/api/apps/{id}/config
app key
Client-visible config: requireInviteForSignup, isPublic, byowEnabled, mode, acceptedCurrencies and createFeeMicro (a decimal string, in microSTX). This is the single source of truth for the invite gate and for what creating costs - do not mirror either in your own env.
GET
/api/apps/{id}/access
app key, user optional
The entry-gate read: { appId, accessPolicy, hasAccess, reason }. A PUBLIC app answers hasAccess: true. For a GRANTED app, reason is UNAUTHENTICATED without a session token and NO_GRANT for a signed-in user with no active grant, and null when access is held. 404 for an unknown or inactive app. This is the read the entry curtain asks, and never the catalog.
GET
/api/apps/{id}/stats
user, entitlement
Aggregate counters for an app. Operator read: needs VIEW_ADMIN_PANEL.
GET
/api/apps/{id}/trending
app key
Trending products in an app by recent edition velocity. window is 7d (default) or 30d; limit is 1-25, default 10.
GET
/api/apps/{id}/random
app key
A random sample of published page products from an app, each with its feedback notes: count is 1-50 (default 1), excludeOwned names an address to skip. Never cached, since a cached random is not random.
What happened in a window, across apps: { window, published, collected, hottest }. published and collected are { total, byApp: [{ sourceAppId, count }] }; hottest ranks products by editions collected in the window, in the same row shape as /api/apps/{id}/trending. The window is window (24h default, 7d, 30d) or since, an ISO time within the last 31 days, for a day that starts at a reader's own midnight. appIds (comma-separated) limits every count to those apps; limit is 1-25, default 10. Counts only, never amounts.
GET
/api/fees/estimate
app key
Estimate the fee for an operation before you build the transaction.