Documentation

Discovery API

Self-documenting endpoints that serve API descriptions as Markdown for AI agents and integrators.

The Discovery API is a public, unauthenticated endpoint that serves the platform's own integration documentation as machine-readable Markdown. It's designed to be the first thing an AI agent or MCP server reads when figuring out how to call AppEngine — fresher than any cached doc, and version-controlled with the code.

What it is

A handful of Markdown files in /Users/imzee/projects/appengine/docs/discovery/ (00-index.md, 01-auth.md, 02-data.md, 03-sites.md, 04-storefront.md, 05-crm.md, 09-sales-channels.md, 11-client.md) served verbatim by DiscoveryController. Each file documents one domain — what it does, the headers it expects, the endpoints it exposes, and worked curl examples. The files are hand-maintained alongside the controllers they describe.

Three things make this useful for AI integrations:

  1. Always fresh — edits go live the moment they're deployed; there is no doc-publishing pipeline drift.
  2. Public — no auth required to read. An agent can fetch it before it has any credentials.
  3. Stable index00-index.md is canonical. Start there, follow links, find the section you need.

Endpoints

GET/discoverNo auth
GET/discover/listNo auth
GET/discover/{name}No auth

The controller is mounted at /discover (note: not /discovery — confirm the prefix in your deployment). All routes are decorated @PublicRoute() and respond with Content-Type: text/markdown; charset=utf-8.

The index file

GET /discover returns 00-index.md — the entry point. From the source:

Appmint is a multi-tenant SaaS platform that bundles a CMS, commerce, CRM, banking, HR, AI, and integration layer behind one API. Every organization (tenant) is isolated by an orgId. Inside an org you have Users (staff who run the org) and Customers (end-buyers of the org's services).

The index covers authentication headers, principal types (User vs Customer), the BaseModel\<T\> envelope, the universal CRUD endpoint, naming conventions, and a module map that links to every other discovery doc.

Listing available docs

GET /discover/list returns a JSON envelope (the only non-Markdown response from this controller):

{
  "baseUrl": "https://appengine.appmint.io/discover",
  "files": [
    { "file": "00-index.md", "url": "https://appengine.appmint.io/discover/00-index" },
    { "file": "01-auth.md",  "url": "https://appengine.appmint.io/discover/01-auth" },
    { "file": "02-data.md",  "url": "https://appengine.appmint.io/discover/02-data" },
    { "file": "03-sites.md", "url": "https://appengine.appmint.io/discover/03-sites" },
    { "file": "04-storefront.md", "url": "https://appengine.appmint.io/discover/04-storefront" },
    { "file": "05-crm.md",   "url": "https://appengine.appmint.io/discover/05-crm" },
    { "file": "09-sales-channels.md", "url": "https://appengine.appmint.io/discover/09-sales-channels" },
    { "file": "11-client.md", "url": "https://appengine.appmint.io/discover/11-client" }
  ]
}

An agent can fetch this once, then crawl each url to build its full picture of the API surface.

Fetching a section

GET /discover/{name} serves the file. Either form works: /discover/02-data and /discover/02-data.md resolve to the same file. The handler validates the name against ^[a-z0-9][a-z0-9\-_]*\.md$ to prevent path traversal.

curl https://appengine.appmint.io/discover/02-data

The response is raw Markdown — feed it to your LLM unchanged.

How an AI agent should consume it

1. GET /discover                  -> 00-index.md
2. Parse the module map.
3. Pick the section that matches the user's intent.
4. GET /discover/{section}        -> the relevant Markdown.
5. Read curl examples and endpoint blocks.
6. Construct the call.
7. If unsure, fall back to the Repository Controller (02-data.md).

The index file ends with a ## 8. How to use this doc as an AI agent section that codifies the same flow.

MCP integration shape

If you're wiring AppEngine into a Model Context Protocol server, the Discovery API is the natural source for tool definitions. A minimal MCP tool:

{
  "name": "appmint_discover",
  "description": "Fetch a section of the AppMint API discovery docs.",
  "inputSchema": {
    "type": "object",
    "properties": {
      "section": {
        "type": "string",
        "description": "Section name without extension, e.g. '02-data', '04-storefront'. Pass empty for the index."
      }
    }
  }
}

The implementation is one HTTP GET. Since the docs are public and small (hundreds of KB total), an MCP server can also pre-fetch them at startup and serve from cache, refreshing on a schedule.

Caching

Each Markdown file is read from disk on every request. There's no server-side caching. With small files and warm filesystem buffers this is fine, but downstream proxies (CDN, reverse proxy) can safely cache responses for minutes — the docs change rarely.

Cache-Control headers are not currently set by the controller; check your edge cache rules.

Error responses

CodeMeaning
400Section name failed the safe-name regex (path-traversal attempt or weird characters).
404The named file doesn't exist on disk. The handler logs the miss and surfaces a clean 404.
500The docs directory is unreadable — usually a deployment bug (file not packaged) rather than a runtime issue.

Updating the docs

The discovery files live in source control: appengine/docs/discovery/*.md. Edits are reviewed alongside controller changes and ship with the same deploy. There is no separate publishing step.

This puts a small but real burden on every developer adding an endpoint: update the matching discovery section in the same PR. The trade-off is documentation that's never out of date relative to the running code.

What's NOT here

  • The discovery API does not auto-generate docs from controllers via reflection or decorators. The Markdown is hand-written.
  • It is not a Swagger/OpenAPI replacement. AppEngine does ship Swagger — see /api (or your deployment's Swagger path) — for an interactive type-level reference. Discovery and Swagger are complementary: Swagger gives you exact request/response schemas; Discovery gives you intent and worked examples.
  • It is not versioned. There's no /discover/v2/. When the API breaks compatibility, the docs are updated in place.

For raw HTTP conventions — headers, error envelope, auth combinations — see Raw REST.