Function API
Sell an answer, priced per call.
Open in
Hollow: the rungs, private to you. Filled: the one Action the caller sees. The point marks the move that pays you.
A Function API sells an answer computed when asked. Each Verb names its Function kind, which sets how long the answer takes and what it costs you. The caller sees one Verb, one price and one Action, whichever kind does the work.
import { define, code, generative, agentic, human, escalate } from 'apis.dev'
import { sectorFromTable } from './sectors'
/** Answers about any company by its domain, from a score in milliseconds to a person's check in hours. */
export default define({
name: 'summaries', domain: 'summaries.apis.dev',
Company: {
domain: 'url!#',
score: code((c) => ({ score: c.domain.endsWith('.ai') ? 80 : 50 })), // computes
summarize: generative('Two sentences on what {domain} sells', // writes
{ returns: { summary: 'string' } }),
research: agentic('Find the head of sales at {domain}', // researches
{ returns: { headOfSales: 'string' } }),
verify: human('Call and confirm the head of sales', // decides
{ role: 'researcher', within: '24h', returns: { confirmed: 'boolean' } }),
classify: escalate([ // one Verb, three kinds
code(sectorFromTable),
generative('The sector {domain} sells into, from the list'),
human('Read the site and pick the sector', { role: 'researcher', within: '24h' }),
], { returns: { sector: 'string' }, check: (out) => out.sector !== 'unknown' }),
},
Text: { // on no stored Noun
translate: generative('Translate {text} into {to}',
{ input: { text: 'string', to: 'string' }, returns: { text: 'string' } }),
},
offer: {
'Company.score': 0.001, 'Company.summarize': 0.02,
'Company.research': 0.5, 'Company.verify': 5,
'Company.classify': 0.04, // one price, whichever kind answers
'Text.translate': 0.01,
},
})The four kinds
| Kind | What it does | How long | What runs it | In summaries | Price |
|---|---|---|---|---|---|
| Code | computes | milliseconds | your function, isolated per call | Company.score | $0.001 |
| Generative | writes | seconds | a prompt through the model router | Company.summarize | $0.02 |
| Agentic | researches, with tools | minutes | an agent whose every tool call passes the gate | Company.research | $0.5 |
| Human | decides | hours or days | a task in a Role's queue | Company.verify | $5 |
returns types the output on every Interface: the Action, the MCP outputSchema, OpenAPI and the SDK. A generative or agentic answer is stamped Inferred, and a person's answer Stated, so the caller knows the basis of every value.
| Thing | States | What moves it |
|---|---|---|
| An Action | pending with its reason, then done, failed or cancelled; refused never starts | The kind's work, a cancel, or a check at the gate |
| A rung of a ladder | tried, then passed or failed, and a failed rung hands on to the next | The Verb's check on the rung's output |
| A person's task | open, claimed, done; or expired | A worker in the Role claims and answers it; within lapses it, and the Action fails at no charge |
| A model call | routed, then answered, or fell_back to the next model | The model router; the caller sees one answer and one price |
Escalation
escalate puts several kinds behind one Verb, cheapest first. Each rung runs only when the one before fails the Verb's check, so a person sees only the hard calls. The rungs are private: the caller sees the Action, its reason while it waits, and the Provenance of the answer.
A domain the table and the model both miss reaches a researcher. The call answers at once, and the Action waits on the person.
curl -X POST https: //summaries.apis.dev/ companies/ obscure.io/ classify \
-H "Authorization: Bearer $SUMMARIES_KEY" \
-H "Max-Cost: 0.10"HTTP/1.1 202 Accepted
Location: /actions/ act_4
Retry-After: 3600
X-Cost: price= 0.04, currency= "USD"
X-Request-Id: req_3e81c0d47a9b52f61e07
{
"id": "act_4",
"verb": "Company.classify",
"status": "pending",
"reason": "AwaitingWorker",
"until": "2026-10-28T09: 00: 00Z",
"poll": "/actions/ act_4"
}When the researcher answers, the Action is done with "provenance":, and its receipt names the Version and the $0.04. If no one claims the task by until, it fails, and the reserved price is released.
Pricing by kind
A Function API is priced per call, and each Verb has its own price. The kinds set the usual range: $0.001 to compute, $0.02 to write, $0.5 to research, $5 for a person. A failed or cancelled Action costs nothing, and a call above its Max-Cost is refused before it runs.
An escalating Verb has one price. When a call climbs to a dearer rung, you carry the difference, and the caller pays the same $0.04.
Deploy prints your margin at the rate each rung was reached over the last 10,000 calls, or at the Test twin's estimate at first. A price below that cost is refused with below_cost.
$ npx apis.dev deploy
✓ Company.classify 0.04 · code 100% · generative 30% · human 1% · cost 0.0213 · margin 47%
✓ published v4 to https: //summaries.apis.devThe print is yours alone. As the model answers more of the hard calls, the human rate falls and the margin rises. The Verb and its price stay the same.
Contracts and the platform's part
| You declare | The platform does |
|---|---|
A Verb, its kind and its returns | Serves it on every Interface, types its output everywhere, meters it once and prices it from the Offer |
| A prompt | Routes it through the model router, falls back on a failure, uses a Customer's own model key when the Offer allows it, and counts tokens as your cost |
| An agentic Verb | Runs the agent with tools drawn from your Verbs and Sources, each call through the gate under the run's mandate, its credentials never in a prompt |
A human Verb, its Role and within | Raises a task in the Role's queue, routes it by skill and credential, lapses it on time, and keeps who answered |
escalate and a check | Tries each rung in order, keeps every rung's output and verdict in the trace, and prints the margin at the measured rates |
| A price per Verb | Reserves it at the gate, captures it on done, releases it on a failure, and prints it on /pricing and the offer card |
| Subsystem | What a Function API takes from it |
|---|---|
| Definition and compile | The kind per Verb, the ladder, the margin print and below_cost |
| Identity, access and policy | Keys, mandates for agent callers, and the Role and credential a human Verb needs |
| Model and records | The Noun a Function acts on, and fields filled from a Verb's latest output |
| Data and Sources | What a prompt or an agent reads, at each Source's cost |
| Runtime | The four kinds, the model router, the gate, and the Action |
| Work | Tasks, queues and leases for the human kind |
| Commerce | The price per call, the reservation, the receipt, and refunds by rule |
| Interfaces and distribution | One tool per Verb over MCP, the SDK method, and quote on the offer card |
| Trust and operations | Evals per kind, success and latency judged from outside, and the trace of every rung |
What Customers and their agents meet
- A price before the call.
/pricingand the offer card list each Verb's price, andquotereturns it at no charge. - One Action for every kind. A fast kind answers done; a slow one answers 202 with where to poll, or holds the call open with
Prefer:.wait - The basis of every answer. Provenance says whether code, a model or a person wrote it.
- No charge for a miss. A failed, lapsed or cancelled Action costs nothing.
An agent finishes the same path with no UI:
- It reads the offer card: price per Verb, success rate and median time, judged from outside.
- It calls
classifyCompanyover MCP withMax-Cost, under its mandate. - It subscribes to the Action and resumes on
done, with no polling. - It keeps the signed receipt, and disputes with it when the answer misses the terms.
| Nounthe shape you promise | Verbwhat can be done to it | Sourcewhere its data comes from | Triggerwhat reacts to a change | Offerthe price |
|---|---|---|---|---|
| the Noun it acts on | a Function: code, a model, an agent or a person | none | none | a price per call, by kind; a failure is free |