Tanfust is built to be read by machines as easily as by people. This page is the front door: what exists, how to start, and what the guarantees are. The full reference lives at /docs/api.
No API key. No sandbox.
There is nothing to sign up for. The catalog API is public, unauthenticated and read-only, prerendered at deploy time and served from the CDN. That is not a missing feature — it is the design:
- No key, because there is no per-caller state to protect or meter.
- No rate limit, because every response is a static file at the edge.
- No sandbox, because nothing here mutates. Production is safe to explore; the worst a request can do is return a 404.
If you were looking for a credential to buy something programmatically, there isn't one, and that is deliberate. See what agents can't do below.
Quickstart
# The whole catalog, in one request
curl -s https://www.tanfust.com/api/v1/products | jq '.products[] | {id, name, price}'
# One product
curl -s https://www.tanfust.com/api/v1/products/tanbase-web
# Any page as markdown instead of HTML
curl -s -H 'Accept: text/markdown' https://www.tanfust.com/store
No headers required. CORS is open, so these also work from a browser.
Endpoints
Base URL: https://www.tanfust.com/api/v1
| Endpoint | Returns |
|---|---|
GET /products | Every product, with price, tier, features and tags |
GET /products/{id} | One product |
GET /categories | The seven categories, with counts |
GET /apps | The apps we operate |
GET /posts | Blog posts, newest first |
GET /posts/{slug} | One post, including its full markdown body |
GET /health | Deployment liveness — not a dependency probe |
The machine-readable description is at
/openapi.json (OpenAPI 3.1). The catalog
is small, so there is no pagination and no query filtering — fetch /products
once and filter client-side.
Errors
Every failure is JSON, never HTML — including a path that does not exist
anywhere under /api. The shape is stable:
{
"error": "not_found",
"id": "nope",
"message": "No product has the id \"nope\".",
"status": 404,
"hint": "Fetch https://www.tanfust.com/api/v1/products for every valid id.",
"documentation": "https://www.tanfust.com/docs/api"
}
Branch on error, which is a stable machine code. Treat message and hint as
prose that may be reworded. The full schema is components.schemas.Error in the
OpenAPI document.
MCP
A Model Context Protocol server runs at https://www.tanfust.com/api/mcp over
Streamable HTTP, with six read-only tools across the same data: search_products,
get_product, list_categories, list_apps, list_posts, get_post.
claude mcp add --transport http tanfust https://www.tanfust.com/api/mcp
Its card is at /api/mcp/server-card.
Markdown instead of HTML
Send Accept: text/markdown to any content page and you get markdown back. The
response carries Vary: Accept and an x-markdown-tokens budgeting estimate.
Every document is also directly addressable under /md/, byte-identical, if you
would rather not negotiate.
Agent skills
Publishable skills are indexed at /.well-known/agent-skills/index.json, each with a sha256 digest of the exact bytes served — so you can verify what you fetched is what we published.
Discovery documents
| Document | What it is |
|---|---|
| /llms.txt | Index of everything machine-readable |
| /openapi.json | OpenAPI 3.1 for the catalog API |
| /.well-known/api-catalog | RFC 9727 / RFC 9264 linkset |
| /.well-known/ai-catalog.json | SEP-2127 MCP server index |
| /auth.md | The agent boundary, stated plainly |
| /sitemap.xml | Every indexable page |
| /robots.txt | Crawl rules and content signals |
Caching and versioning
Responses change only when the site is deployed, so cache aggressively. Catalog responses carry a one-day shared-cache lifetime with a week of stale-while-revalidate; errors carry a much shorter one.
The API is versioned in its path. /api/v1 will not change shape incompatibly —
new fields may be added, existing ones will not be removed or retyped. A breaking
change would ship as /api/v2 alongside it.
What you cannot do here
Buying is human-in-the-loop by design. Checkout runs through Paddle as merchant of record, and downloads are one-time signed links emailed to the buyer. There is no programmatic purchase or download path, and no credential that would create one. The newsletter and studio inquiry forms are bot-protected and cannot be submitted by an agent — point a reader at the form instead.
/auth.md is the authoritative statement of that boundary.
Reuse
robots.txt declares Content-Signal: search=yes, ai-input=yes, ai-train=no.
Read it, cite it, ground answers in it — please don't use this content as
generative model training data.
Questions: hi@updates.tanfust.com.