API only: what a Customer gets without an App
What a Customer of Headless SaaS reaches with no App: five Interfaces, the machine registers an Agent reads, keys, and prices per call.
A Customer of API-only Software works through code, not screens: its developers and Agents call the Startup's Verbs directly. Headless SaaS lists five Interfaces, and each derives from the one definition.
Five Interfaces from one definition
Every Noun the Startup declares answers on each Interface under the same name, such as Lease.get. Here is one Lease of leaseclock.com, read on each.
| Interface | A Customer uses it to | Reads one Lease as | Served |
|---|---|---|---|
| API | call from any program over HTTPS | GET /leaseclock.com/leases/{id} | reads |
| SDK | call from TypeScript, with types | $.Lease.get({ id }) | reads |
| CLI | script from a terminal or a coding Agent | npx startup-builder do Lease.get --json '{"id":"lease_1"}' | reads |
| MCP | let an Agent run a short program | do with $.Lease.get({ id: 'lease_1' }) | reads |
| Webhooks | hear each Event as it happens | Lease.renewed, signed | waits for write Verbs |
A read returns the record as JSON with its $id, the one URL that names it on every Interface. The same URL answers in Markdown for a caller that sends Accept: text/markdown.
PlanWrite Verbs and webhooks
In the design, Lease.create, Lease.update, Lease.renew and Lease.terminate are served on all four Interfaces. Each call returns an Action: done, or refused with the rule the Verb broke. A webhook delivers each write's Event, such as Lease.renewed, signed so the Customer can check where it came from.
What an Agent reads first
An Agent that knows the Startup's Domain finds the rest from four machine registers. Each is generated from the same definition as the Interfaces.
| Register | At | Holds |
|---|---|---|
| OpenAPI | /openapi.json | every operation, its inputs and its response schema |
llms.txt | /llms.txt | every docs page, one line each, for a language model |
agents.json | /agents.json | the Interfaces, how to authenticate, and the Offers |
| Markdown twins | each docs page as .md, each record with Accept: text/markdown | the same facts as the HTML in fewer tokens |
Keys and prices
PlanKeys from the Portal
In the design, every call carries a key that names the Customer. The key reaches only that Customer's Tenant, so no call reads another Customer's records.
A Customer makes, rolls and revokes its own API Keys in the Portal, with APIKey.issue, APIKey.roll and APIKey.revoke. The secret shows once. Key requests never reach the Startup's team.
PlanPrices per call
The Portal around the API
An API-only Customer still signs in, takes a key, watches usage and pays. Those screens are the Portal, and for an API product the apis.dev Portal holds them: one key and its calls, in HTML, Markdown and JSON.
Software adds people to that Portal: members and seats, a switcher between workspaces, and Offers priced per seat. Portal screens for Software: members, seats and plan lists those screens and the data states each one handles. When the Customer's own people need screens for the records, API only or with an App weighs the cost, and SaaS adds the App.
Verb inputs: what a form needs
Why a Verb that takes only its record gets a working button, and why a Verb with typed inputs gets a button but no form in the Admin.
Portal screens for Software: members, seats and plan
The Portal screens Software adds over an API product's Portal, and the data states each screen handles: members, seats, workspaces and per-seat Offers.