Skip to content
v0.3

Surfaces

A surface is a way to reach the port. Forge ships four, and none of them is written by hand: each is generated from the command and read registries, so they cannot fall out of step with the kernel or with each other.

SurfaceWhat it is for
APIHTTP. The one every other surface is built on, and the one your ERP will use.
CLIA terminal. Operations, scripts, and looking at things quickly.
MCPAn agent. The registry exposed as tools, with the kernel’s own scope check behind it.
SDKTypeScript. Typed per command name, results included.

Writes go to /v1/commands/<name> with a tenant credential. Platform commands — the ones marked System: yes on their reference page — go to /v1/control/commands/<name> and need a platform credential instead. They are a different actor reaching a different gate, not the same call with more permission.

⚠️ Public commands are on neither. Building a cart, placing an order, a shopper logging in, starting a payment — those are anonymous, and they are served by faces of their own: /v1/cart, /v1/checkout, /v1/customer, /v1/operator, /v1/payment. No credential; the store travels in the x-forge-store header, and possession of the relevant id is the capability. A handful of public commands are deliberately on no external face at all — the ones that move money are reached only by the kernel itself, on a verified provider verdict.

Reads have three faces, and the difference between them is who is allowed to ask:

  • GET /v1/read/<name> — public. No credential. The store resolves the tenant. This is what a storefront calls, including from a browser.
  • GET /v1/read/internal/<name> — internal. A tenant credential is required and the tenant comes from the caller’s identity, never from a parameter. Gated by scope.
  • GET /v1/control/read/<name> — control. The platform face.

⚠️ A public read is PII-safe by decision, even for the party holding the identifier. A guest reading their own checkout gets j***@e***.com, not the address they typed. That is deliberate: possession of a cart id is not proof of identity, and the front-end that typed the value is the one that should still have it.

This is the part worth internalising, because it shapes how you build on Forge.

The read port is not “the API the storefront happens to use”. It is the contract, designed to be consumed by anything: your storefront, a native app, a partner’s marketplace integration, an agent doing research. It answers in stable shapes with stable names, and it does not assume a browser.

The storefront, the checkout and the admin that ship with Forge are consumers of that contract, not layers of the kernel. They are a reference implementation — complete and maintained by us — and you can replace them piece by piece or entirely. Whatever you build talks to the same kernel through the same door, with the same guarantees.

⚠️ The storefront does not include the checkout. They are two separate deployables served from one origin, split by path: the storefront is the half you are most likely to rebuild, and the checkout — checkout, account, sign-in, orders — is hosted by us and extended through theme, chrome, slots and apps rather than through a fork. Forking it stays available; it stopped being the price of owning your storefront.

That is why “own your storefront” is a supported outcome rather than an escape hatch. See the guide.

What is generated, and what that means for you

Section titled “What is generated, and what that means for you”

The reference pages, the OpenAPI document, the CLI dispatch table, the MCP tool list and the SDK’s types all come out of the same registries in one pass. CI regenerates them and fails the build if the committed bytes differ.

For you, the practical consequence is: the reference cannot lie about what exists. If a command is on this site, it is in the kernel with that exact input schema. If it is not, it does not exist.

Every authenticated response carries RateLimit-* headers — on success, not only on a 429. The state of your budget is part of the response contract, so you can design a backoff before you need one.

The subject of the limit is the credential, per tenant, never the account. Two keys belonging to the same customer have independent budgets, so one runaway integration cannot take the others down.