REST
Some of Litestore's REST routes are stable for outside callers, and each group of routes checks the caller in its own way.
Route handlers under app/api serve callers that can't use a server action or an oRPC procedure. A payment provider posting a webhook, a browser uploading a file and an AI agent reading the catalog all reach Litestore this way.
Request
Litestore publishes an OpenAPI document at app/api/openapi.json that describes some of these routes. We wrote it for AI agents and outside integrations, and it deliberately covers fewer routes than the folder contains.
Keep this difference in mind. A route under app/api is not public just because it is there. The contract lists the routes we invite outside callers to depend on. Every other route is internal code that still happens to be reachable over HTTP.
OpenAPI contract
app/api/openapi.json/route.ts builds the spec inside its GET handler instead of serving a static file. It does this so the servers entry can use the deployment's own base URL, which it reads from env.NEXT_PUBLIC_SITE_URL. A static file would need a hardcoded host, and that host would be wrong in every environment but one.
The document calls itself the AI Commerce API:
const spec = {
openapi: "3.0.3",
info: {
title: `${config.site.name} AI Commerce API`,
version: "1.0.0",
},
servers: [{ url: baseUrl, description: "Production server" }],
tags: [
{ name: "Discovery", description: "API discovery and capabilities" },
{ name: "Products", description: "Product catalog operations" },
{ name: "Recommendations", description: "Product recommendations" },
{ name: "Tracking", description: "Event tracking" },
{ name: "AI", description: "AI-powered content generation" },
],
// …
}Five tags group everything the document advertises:
| Tag | What it covers |
|---|---|
| Discovery | API discovery and capabilities |
| Products | Product catalog operations |
| Recommendations | Product recommendations |
| Tracking | Event tracking |
| AI | AI-powered content generation |
The document currently describes these paths:
/.well-known/ai-commerce
/api/capabilities
/api/products
/api/products/feed
/api/products/{id}
/api/recommendations
/api/track
/ai/v1/suggest-categoriesThe last path is stale: app/ai/v1/ now holds only admin-chat and fill-product, and the spec lists neither.
The spec is hand-written
The document is a literal inside the route handler. Nothing generates it from the handlers it describes, and only a comment says to keep it in sync. A new endpoint won't appear here until someone adds it.
Discovery
We designed the API so that an agent can arrive at the store's domain and work out the endpoints by itself, without a person handing it a URL.
/.well-known/ai-commerce
This route lists the endpoints, the capabilities and the authentication each one needs. An agent should try it first, and it links on to the OpenAPI document.
/api/capabilities
This route reports whether the platform is ready, which AI providers are configured, which features are on and which currencies the store uses.
/api/capabilities needs a signed-in admin session. The spec lists it under Discovery, but it is the one discovery route that isn't open. It shows how the operator configured the store, and shoppers don't need that.
Route groups
The route tree splits into seven groups. They differ mostly in who may call them and how the caller proves it.
| Group | Routes | How the caller proves who it is |
|---|---|---|
| Commerce for agents | products, recommendations, cart, track | None for public reads (rate limited per IP); the cart routes use the shopper's cart session or a service key with a cart scope. We wrote the OpenAPI document for these routes. |
| Discovery | .well-known/ai-commerce, .well-known/ucp, capabilities, openapi.json | None, except capabilities, which needs an admin session. |
| MCP | mcp, mcp/admin | The shopper route is public and rate limited per IP. The admin route needs a service key with the admin:mcp scope, sent as a Bearer token. |
| Webhook management | webhooks, webhooks/[id], webhooks/events | A service key with the read or write:webhooks scope. |
| Inbound webhooks | stripe/webhooks, webhooks/resend | The provider's signature on the request body. No Litestore credential is involved. |
| Platform | inngest, health, upload, media, messages/upload, reviews/upload, locale, unsubscribe, feed-events | Each handler does it differently. |
| Admin and AI | admin, ai | An admin session. data serves static tag and option presets without auth, and rpc (oRPC) takes a service key. |
The platform routes exist because the platform needs an HTTP endpoint, not because an integrator asked for one. Each of them handles auth differently, so read the handler instead of assuming a rule for the group.
For the inbound webhooks, Stripe or Resend calls the route, and the signature they put on the request body proves who sent it.
Other routes
The MCP routes, the webhook management routes and the inbound provider webhooks appear in neither the OpenAPI contract nor the oRPC router. We left them out on purpose. Each one has its own kind of authentication, and a shared contract would describe them wrongly.
Integrators don't call a webhook route. A specific provider posts to it, Litestore checks that provider's signature, and the provider determines the shape of the request.
The MCP routes speak JSON-RPC 2.0 instead of REST. An MCP client finds their tools through tools/list, not through an OpenAPI document, so no MCP client would read an OpenAPI description of them.
Adding routes
Use a server action when Litestore's own admin or storefront UI is the caller.
For outside integrators to depend on the new route, writing the handler is only half the work, because the hand-written spec won't pick it up by itself.
A route becomes part of the published contract when someone adds it to app/api/openapi.json/route.ts, and not before.
Related
Overview
Server actions handle admin and storefront writes, oRPC at /api/rpc serves service-key callers, and /api/openapi.json describes the REST endpoints.
MCP
AI assistants connect to the store over MCP, with public shopper tools at /api/mcp and the admin's gated tool kit at /api/mcp/admin.
Webhooks
Litestore signs and retries outbound webhook deliveries, disables a failing endpoint automatically, and receives Stripe and Resend callbacks on separate routes.