# Access levels URL: /agents/access-levels · Id: `page:agents/access-levels` > A Role says what work a seat does; an Access Level says what a person may open and change in the app, and it is never a Role. An [Access Level](/business/nouns/access-level) is a named preset of [Permissions](/business/nouns/permission) a [Worker](/business/nouns/worker) holds in a namespace, such as owner or viewer. It is never a [Role](/business/nouns/role): the Role is the work, the Access Level is the reach. ## Two questions, two records | Record | Answers | Example | | --- | --- | --- | | Role | What work is this seat accountable for, and which [Verbs](/business/nouns/verb) does that work need? | The [Billing Specialist](/agents/finance/billing-specialist) bills, collects and refunds up to $100 | | Access Level | What may this Worker read and change anywhere in the [Startup](/business/nouns/startup)? | A contractor reads every record and changes nothing | An [Agent](/business/nouns/agent) in a seat calls exactly its Role's Verbs. A person also signs in to the app, so they hold an Access Level as well, and it never widens what their seat may call. ## The four levels | Access Level | May | | --- | --- | | Owner | Call every Verb on every [Noun](/business/nouns/noun), one-way Verbs included, each within its delay window | | Admin | Read everything and make every two-way change, access included; one-way Verbs stay with the owner | | Member | Read everything and make two-way changes, except to the records that decide access | | Viewer | Read everything and change nothing | The records that decide access are Roles, Permissions, [Mandates](/business/nouns/mandate), [Limits](/business/nouns/limit), [Settings](/business/nouns/setting), [Guards](/business/nouns/guard) and [Secrets](/business/nouns/secret). Every Noun page shows its own grid by Access Level. ## Common cases | You want | Seat | Access Level | | --- | --- | --- | | A cofounder running engineering | [Engineering Lead](/agents/engineering/engineering-lead), shared with its agent | Admin | | A contractor who answers support for one [Team](/business/nouns/team) | [Customer Lead](/agents/customer/customer-lead) | Member | | An accountant who reads the books at year end | None | Viewer | | An investor reading monthly numbers | None | Viewer, or a scoped room from [`Startup.read`](/business/nouns/startup/read) | A person with no seat does no work in the Startup; they only read or change what their Access Level allows. [Invite a person to a Role](/agents/invite-a-person-to-a-role) gives them both at once. # Add a role to the team URL: /agents/add-a-role · Id: `guide:add-a-role` > Create a Role for work no seat on the chart covers, and seat an agent in it in two calls. Create a [Role](/business/nouns/role) for work no seat on the chart covers, and seat an [Agent](/business/nouns/agent) in it. Your agent first checks that no seat already answers to the name: a bookkeeper is the [Finance Lead](/agents/finance/finance-lead). **Before it runs** - You leave the chat: Never: it all happens in the chat. ## What you get - 1 new seat with its job, duties and limits written down (Role) - 1 agent in the seat, with its own name in your business (Agent) - 1 tools: only what its duties need (Permission) - 1 questions come to you until a team lead takes them (Role) ## Your agent does **For agents** - Guide: `guide:add-a-role`, status `live`. Page: [/agents/add-a-role.md](/agents/add-a-role.md). - Approval: none. Run it when the founder asks. - Leaves the chat: never. - Run: call the steps in order, each through the API, SDK, CLI or MCP tab below; a later step passes the `$id` an earlier one returns. Each value marked example is the sample business’s: pass the founder’s own. | Step | Verb | Inputs (type, required, this guide’s value) | Returns | | --- | --- | --- | --- | | 1 | [`Role.create`](/business/nouns/role/create) (`verb:Role.create`) | `name` string, required: example `"Maintenance Coordinator"`; `responsibilities` text: example `"Books a vendor for every repair request within one business day. Tells the resident the visit time."` | `role` Role | | 2 | [`Role.staff`](/business/nouns/role/staff) (`verb:Role.staff`) | `role` Role (an id), required: the `$id` step 1 returns; `worker` Worker (an id), required: example `"agent_maintenance_coordinator"` | `role` Role | Returns: the last call answers with `role` and its `action`, whose `status` is `done`, `pending` (waiting on an Approval or a Worker), `failed`, `canceled` or `refused`: ```json { "api": "https://api.sb/leaseline.app", "role": { "$id": "https://api.sb/leaseline.app/roles/role_1", "$type": "Role", "name": "Maintenance Coordinator", "responsibilities": "Books a vendor for every repair request within one business day. Tells the resident the visit time.", "status": "filled" }, "action": { "$id": "https://api.sb/leaseline.app/actions/action_1", "operation": "Role.staff", "status": "done" }, "links": { "self": "https://api.sb/leaseline.app/actions/action_1" } } ``` Next: offer “Put it on the Operations Team”, or “Let it book repairs up to $300 without asking”. Calls: `Role.create` → `Role.staff` Ask: ```text Add a maintenance coordinator to the team. I need someone to book repair vendors. Create a new role for leasing. ``` API: ```bash # 1. Role.create ROLE=$(curl -X POST https://api.sb/leaseline.app/roles \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"name":"Maintenance Coordinator","responsibilities":"Books a vendor for every repair request within one business day. Tells the resident the visit time."}' | jq -r '.role["$id"] | split("/") | last') # 2. Role.staff curl -X POST https://api.sb/leaseline.app/roles/$ROLE/staff \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"worker":"agent_maintenance_coordinator"}' ``` SDK: ```ts import { $ } from 'startup-builder' const role = await $.Role.create({ name: 'Maintenance Coordinator', responsibilities: 'Books a vendor for every repair request within one business day. Tells the resident the visit time.' }) await $.Role.staff({ role: role.$id, worker: 'agent_maintenance_coordinator' }) ``` CLI: ```bash ROLE=$(npx startup-builder do Role.create --json '{"name":"Maintenance Coordinator","responsibilities":"Books a vendor for every repair request within one business day. Tells the resident the visit time."}' | jq -r '.role["$id"] | split("/") | last') npx startup-builder do Role.staff --json '{"role":"'"$ROLE"'","worker":"agent_maintenance_coordinator"}' ``` MCP: ```json { "name": "do", "arguments": { "code": "const role = await $.Role.create({ name: 'Maintenance Coordinator', responsibilities: 'Books a vendor for every repair request within one business day. Tells the resident the visit time.' })\nreturn await $.Role.staff({ role: role.$id, worker: 'agent_maintenance_coordinator' })" } } ``` ## Change it - Put it on the Operations Team. - Let it book repairs up to $300 without asking. - Have it escalate to the Operations Lead, not me. ## Under the hood - Systems: [Workforce](/systems/workforce), [Work queue](/agents/work-queue) - Nouns: [Role](/business/nouns/role), [Agent](/business/nouns/agent), [Permission](/business/nouns/permission), [Team](/business/nouns/team) - Events: [`Role.staffed`](/business/events/Role.staffed) Write the contract before the seat opens: why it exists, the duties, the [Metric](/business/nouns/metric) that judges it and its [Limits](/business/nouns/limit). [Role contracts](/agents/roles) lists every part. A seat with no result Metric gives its [Role Review](/business/nouns/role-review) nothing to read. # Add a team URL: /agents/add-a-team · Id: `guide:add-a-team` > Create a Team for work no department owns, then open its lead seat and put an agent in it, in three calls. A [Team](/business/nouns/team) groups the [Roles](/business/nouns/role) that do one kind of work under one owner. Add one when no department owns the work; for one more seat on a Team, [add a role](/agents/add-a-role). **Before it runs** - You leave the chat: Never: it all happens in the chat. ## What you get - 1 team on the org chart, with its mission written down (Team) - 1 lead seat on that team, with its duties (Role) - 1 agent in the lead seat (Agent) ## Your agent does **For agents** - Guide: `guide:add-a-team`, status `live`. Page: [/agents/add-a-team.md](/agents/add-a-team.md). - Approval: none. Run it when the founder asks. - Leaves the chat: never. - Run: call the steps in order, each through the API, SDK, CLI or MCP tab below; a later step passes the `$id` an earlier one returns. Each value marked example is the sample business’s: pass the founder’s own. | Step | Verb | Inputs (type, required, this guide’s value) | Returns | | --- | --- | --- | --- | | 1 | [`Team.create`](/business/nouns/team/create) (`verb:Team.create`) | `mission` text, required: example `"Inspects every managed unit once a year and books the repairs it finds."` | `team` Team | | 2 | [`Role.create`](/business/nouns/role/create) (`verb:Role.create`) | `name` string, required: example `"Field Lead"`; `responsibilities` text: example `"Schedules each unit’s yearly inspection and files the repairs it finds."`; `team` Team (an id): the `$id` step 1 returns | `role` Role | | 3 | [`Role.staff`](/business/nouns/role/staff) (`verb:Role.staff`) | `role` Role (an id), required: the `$id` step 2 returns; `worker` Worker (an id), required: example `"agent_field_lead"` | `role` Role | Returns: the last call answers with `role` and its `action`, whose `status` is `done`, `pending` (waiting on an Approval or a Worker), `failed`, `canceled` or `refused`: ```json { "api": "https://api.sb/leaseline.app", "role": { "$id": "https://api.sb/leaseline.app/roles/role_1", "$type": "Role", "name": "Field Lead", "responsibilities": "Schedules each unit’s yearly inspection and files the repairs it finds.", "status": "filled" }, "action": { "$id": "https://api.sb/leaseline.app/actions/action_1", "operation": "Role.staff", "status": "done" }, "links": { "self": "https://api.sb/leaseline.app/actions/action_1" } } ``` Next: offer “Put the Maintenance Coordinator on it too”, or “Have the Operations Lead approve its spend”. Calls: `Team.create` → `Role.create` → `Role.staff` Ask: ```text Add a team. Start a field team for property inspections. Create a new department. ``` API: ```bash # 1. Team.create TEAM=$(curl -X POST https://api.sb/leaseline.app/teams \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"mission":"Inspects every managed unit once a year and books the repairs it finds."}' | jq -r '.team["$id"] | split("/") | last') # 2. Role.create ROLE=$(curl -X POST https://api.sb/leaseline.app/roles \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"name":"Field Lead","responsibilities":"Schedules each unit’s yearly inspection and files the repairs it finds.","team":"'"$TEAM"'"}' | jq -r '.role["$id"] | split("/") | last') # 3. Role.staff curl -X POST https://api.sb/leaseline.app/roles/$ROLE/staff \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"worker":"agent_field_lead"}' ``` SDK: ```ts import { $ } from 'startup-builder' const team = await $.Team.create({ mission: 'Inspects every managed unit once a year and books the repairs it finds.' }) const role = await $.Role.create({ name: 'Field Lead', responsibilities: 'Schedules each unit’s yearly inspection and files the repairs it finds.', team: team.$id }) await $.Role.staff({ role: role.$id, worker: 'agent_field_lead' }) ``` CLI: ```bash TEAM=$(npx startup-builder do Team.create --json '{"mission":"Inspects every managed unit once a year and books the repairs it finds."}' | jq -r '.team["$id"] | split("/") | last') ROLE=$(npx startup-builder do Role.create --json '{"name":"Field Lead","responsibilities":"Schedules each unit’s yearly inspection and files the repairs it finds.","team":"'"$TEAM"'"}' | jq -r '.role["$id"] | split("/") | last') npx startup-builder do Role.staff --json '{"role":"'"$ROLE"'","worker":"agent_field_lead"}' ``` MCP: ```json { "name": "do", "arguments": { "code": "const team = await $.Team.create({ mission: 'Inspects every managed unit once a year and books the repairs it finds.' })\nconst role = await $.Role.create({ name: 'Field Lead', responsibilities: 'Schedules each unit’s yearly inspection and files the repairs it finds.', team: team.$id })\nreturn await $.Role.staff({ role: role.$id, worker: 'agent_field_lead' })" } } ``` ## Change it - Put the Maintenance Coordinator on it too. - Have the Operations Lead approve its spend. - Keep it asleep until we pass 500 units. ## Under the hood - Systems: [Workforce](/systems/workforce) - Nouns: [Team](/business/nouns/team), [Role](/business/nouns/role), [Agent](/business/nouns/agent) - Events: `Team.created`, [`Role.staffed`](/business/events/Role.staffed) A Team is asleep until one of its [Processes](/business/nouns/process) is on. [Teams](/agents/teams) shows the eleven every [Startup](/business/nouns/startup) inherits and which are awake at each state. # Answer an approval URL: /agents/answer-an-approval · Id: `guide:answer-an-approval` > Approve, refuse or ask for a change on what waits for you, from your startups.studio inbox, Slack, Microsoft Teams or the iPhone app. Each [Approval](/business/nouns/approval) waits in your startups.studio inbox, and the same card shows in Slack, Microsoft Teams and the iPhone app. Answer it [anywhere](/agents/reach): approve, refuse with a reason, or reply in its thread to ask for a change. **Before it runs** - You leave the chat: Never: it all happens in the chat. ## What you get - 1 inbox in startups.studio with everything waiting on you, most urgent first (Approval) - 1 card in Slack or Microsoft Teams with Approve and Refuse buttons, in the thread about the work (Thread) - 1 iPhone app with the same inbox, for answers on the move (Approval) - 1 daily or weekly email that links to each one (Dashboard) - 1 answer recorded once, wherever you give it first; every other place shows it (Decision) - 1 deadline: unanswered by then, the request is canceled and nothing runs (Action) ## Your agent does **For agents** - Guide: `guide:answer-an-approval`, status `live`. Page: [/agents/answer-an-approval.md](/agents/answer-an-approval.md). - Approval: none. Run it when the founder asks. - Leaves the chat: never. - Run: call the steps in order, each through the API, SDK, CLI or MCP tab below; a later step passes the `$id` an earlier one returns. Each value marked example is the sample business’s: pass the founder’s own. | Step | Verb | Inputs (type, required, this guide’s value) | Returns | | --- | --- | --- | --- | | 1 | [`Approval.approve`](/business/nouns/approval/approve) (`verb:Approval.approve`) | `approval` Approval (an id), required: example `"approval_ads_740"`; `note` text: example `"Yes, for the March campaign only."` | `approval` Approval | Returns: the last call answers with `approval` and its `action`, whose `status` is `done`, `pending` (waiting on an Approval or a Worker), `failed`, `canceled` or `refused`: ```json { "api": "https://api.sb/leaseline.app", "approval": { "$id": "https://api.sb/leaseline.app/approvals/approval_ads_740", "$type": "Approval" }, "action": { "$id": "https://api.sb/leaseline.app/actions/action_1", "operation": "Approval.approve", "status": "done" }, "links": { "self": "https://api.sb/leaseline.app/actions/action_1" } } ``` Next: offer “Refuse it: the March budget is spent”, or “Ask the agent for a cheaper option before I decide”. Calls: `Approval.approve` Ask: ```text What is waiting on me? Show me my approvals. Approve the $740 ad spend. ``` API: ```bash # Approval.approve curl -X POST https://api.sb/leaseline.app/approvals/approval_ads_740/approve \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"note":"Yes, for the March campaign only."}' ``` SDK: ```ts import { $ } from 'startup-builder' await $.Approval.approve({ approval: 'approval_ads_740', note: 'Yes, for the March campaign only.' }) ``` CLI: ```bash npx startup-builder do Approval.approve --json '{"approval":"approval_ads_740","note":"Yes, for the March campaign only."}' ``` MCP: ```json { "name": "do", "arguments": { "code": "return await $.Approval.approve({ approval: 'approval_ads_740', note: 'Yes, for the March campaign only.' })" } } ``` ## Change it - Refuse it: the March budget is spent. - Ask the agent for a cheaper option before I decide. - Send my approvals to Slack too. ## Under the hood - Systems: [Work queue](/agents/work-queue), [Discussions](/agents/discussions) - Nouns: [Approval](/business/nouns/approval), [Action](/business/nouns/action), [Thread](/business/nouns/thread), [Decision](/business/nouns/decision) - Events: [`Approval.approved`](/business/events/Approval.approved) # Approve what agents spend URL: /agents/approve-what-agents-spend · Id: `guide:approve-what-agents-spend` > Set the line above which any agent spend waits for you, then answer each request in your startups.studio inbox, Slack or Microsoft Teams. Set a [Limit](/business/nouns/limit) on what agents spend. Anything above it becomes an [Approval](/business/nouns/approval) that waits for your yes, wherever you [answer approvals](/agents/answer-an-approval). Needs: [Agent](/business/nouns/agent) **Before it runs** - You leave the chat: Never: it all happens in the chat. - First question at Idea: “What amount needs your yes: $100, or every dollar?” ## What you get - 1 $500 a month spending limit on every agent (Limit) - 1 request to you for each spend above it, with the reason, in your startups.studio inbox and in Slack or Microsoft Teams (Approval) - 1 business cardholder, so agents never hold your own card (Card) - 1 single-use card for each approved payment, capped at its amount (Card) - 1 short wait before each payment goes out, so you can still stop it (Action) - 1 line in your books for every payment (Entry) ## Your agent does **For agents** - Guide: `guide:approve-what-agents-spend`, status `live`. Page: [/agents/approve-what-agents-spend.md](/agents/approve-what-agents-spend.md). - Approval: none. Run it when the founder asks. - Leaves the chat: never. - Needs first: [Agent](/business/nouns/agent). - Run: call the steps in order, each through the API, SDK, CLI or MCP tab below; a later step passes the `$id` an earlier one returns. Each value marked example is the sample business’s: pass the founder’s own. | Step | Verb | Inputs (type, required, this guide’s value) | Returns | | --- | --- | --- | --- | | 1 | [`Limit.create`](/business/nouns/limit/create) (`verb:Limit.create`) | `amount` money: example `{"amount":500,"currency":"USD"}`; `period` string: example `"month"` | `limit` Limit | | 2 | [`Approval.approve`](/business/nouns/approval/approve) (`verb:Approval.approve`) | `approval` Approval (an id), required: example `"approval_1"`; `note` text: example `"Yes: the annual renewal for the listing site."` | `approval` Approval | Returns: the last call answers with `approval` and its `action`, whose `status` is `done`, `pending` (waiting on an Approval or a Worker), `failed`, `canceled` or `refused`: ```json { "api": "https://api.sb/leaseline.app", "approval": { "$id": "https://api.sb/leaseline.app/approvals/approval_1", "$type": "Approval" }, "action": { "$id": "https://api.sb/leaseline.app/actions/action_1", "operation": "Approval.approve", "status": "done" }, "links": { "self": "https://api.sb/leaseline.app/actions/action_1" } } ``` Next: offer “Raise it to $1,000 for ad spend only”, or “Refuse the $740 request and tell the agent why”. Calls: `Limit.create` → `Approval.approve` Ask: ```text Ask me before any agent spends more than $500 a month. Nothing over $500 goes out without my yes. Show me what the agents want to spend, and let me approve it. ``` API: ```bash # 1. Limit.create curl -X POST https://api.sb/leaseline.app/limits \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"amount":{"amount":500,"currency":"USD"},"period":"month"}' # 2. Approval.approve curl -X POST https://api.sb/leaseline.app/approvals/approval_1/approve \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"note":"Yes: the annual renewal for the listing site."}' ``` SDK: ```ts import { $ } from 'startup-builder' await $.Limit.create({ amount: { amount: 500, currency: 'USD' }, period: 'month' }) await $.Approval.approve({ approval: 'approval_1', note: 'Yes: the annual renewal for the listing site.' }) ``` CLI: ```bash npx startup-builder do Limit.create --json '{"amount":{"amount":500,"currency":"USD"},"period":"month"}' npx startup-builder do Approval.approve --json '{"approval":"approval_1","note":"Yes: the annual renewal for the listing site."}' ``` MCP: ```json { "name": "do", "arguments": { "code": "await $.Limit.create({ amount: { amount: 500, currency: 'USD' }, period: 'month' })\nreturn await $.Approval.approve({ approval: 'approval_1', note: 'Yes: the annual renewal for the listing site.' })" } } ``` ## Change it - Raise it to $1,000 for ad spend only. - Refuse the $740 request and tell the agent why. - Stop all agent spending until I say so. ## Under the hood - Systems: [Spend management](/systems/spend), [Treasury](/systems/treasury), [Ledger](/systems/ledger) - Nouns: [Limit](/business/nouns/limit), [Approval](/business/nouns/approval), [Mandate](/business/nouns/mandate), [Card](/business/nouns/card), [Entry](/business/nouns/entry) - Events: `Limit.created`, [`Approval.approved`](/business/events/Approval.approved) - Stripe objects: `Issuing Cardholder`, `Issuing Card` # Brakes URL: /agents/autonomy-levels/brakes · Id: `page:agents/autonomy-levels/brakes` > A brake stops one class of effects, such as sends, spend, publishes or price changes, across many Startups at once, until it expires or is lifted. A brake stops one class of effects (sends, spend, publishes or price changes) across a set of [Startups](/business/nouns/startup) at once. Readings trip most brakes; a watcher pulls the rest by hand. ## What a brake stops A brake is a [Setting](/business/nouns/setting) with a scope, the effects it stops, a reason and an expiry. Its scope is a [Portfolio](/business/nouns/portfolio) query: one Startup, a [Cohort](/business/nouns/cohort), every Startup on one [Startup Template](/business/nouns/startup-template) [Version](/business/nouns/version), or the whole Portfolio. Every Startup in scope inherits it. While a brake holds, each new [Action](/business/nouns/action) with a braked effect stays `pending`. Nothing already done is undone; [revert by query](/agents/autonomy-levels/recovery-and-proof#revert-by-query) does that. When the brake lifts, the held Actions resume their review and delay windows. ```ts import { $ } from 'startup-builder' const { brake } = await $.Portfolio.brake({ portfolio: 'directories', query: 'template.version = "4.2.0"', effects: ['publish'], reason: 'Checkout conversion fell below its guardrail on the first three Startups.', until: '2026-11-03T17:00:00Z', }) await $.Portfolio.lift({ portfolio: 'directories', brake: brake.$id, reason: 'Version 4.2.1 fixes checkout.' }) ``` A brake never waits for a window. Stopping is always safe to do at once, so a brake takes effect the moment it is set. ## Automatic brakes | Trip | Reading | What stops | | --- | --- | --- | | Runaway volume | Outbound [Messages](/business/nouns/message), refunds or payouts pass three times their trailing seven-day average in an hour. | That effect, for the Startup that produced it | | Bad version | The first Startups on a new Startup Template Version breach a guardrail [Metric](/business/nouns/metric). | Publishes, for every Startup on that Version | | Guardrail breach | A [Play](/business/nouns/play) rollout breaches a guardrail Metric in its Cohort. | The Play's effects; the rollout reverts | | Shock invoice | A bill arrives at more than three times its trailing average. | Payment of that bill | Each trip records a [Decision](/business/nouns/decision) for the owning [Role](/business/nouns/role) to resolve. A freeze is a brake set ahead of time, such as no price changes across a Portfolio during a holiday week. ## Spend states Every budget runs in one of three spend states. A tripwire moves it down one state at once; moving back up is a Decision. | State | What may be spent | | --- | --- | | `FREE` | Anything inside a standing envelope with tripwires, such as ads up to $200 a day while acquisition cost stays under target. | | `TIGHT` | Only spend against a signed [Campaign](/business/nouns/campaign) order: a [Mandate](/business/nouns/mandate) with an amount, a condition and an expiry. | | `HOLD` | Committed obligations only, such as payroll, taxes and [Invoices](/business/nouns/invoice) owed. Anything new needs an [Approval](/business/nouns/approval) from the Role above. | Every grant carries its condition, its expiry and the budget left, so one approval never becomes open-ended spend. Paying a shock invoice and suspending a paying customer always sit behind `HOLD`. [Spend management](/systems/spend) keeps the states. ## In practice The [Studio](/business/nouns/studio) ships version 4.2.0 of its [Directory](/products/templates/directory) Startup Template to 30 Startups, starting with three. Within an hour, checkout conversion on all three falls below its guardrail. A bad-version brake stops publishes for every Startup on 4.2.0, so the other 27 never receive it. The [Engineering Lead](/agents/engineering/engineering-lead) reverts the three by query and ships 4.2.1, which passes on a fresh cohort of three. The brake lifts, and the rollout continues. # Decision classes URL: /agents/autonomy-levels/decision-classes · Id: `page:agents/autonomy-levels/decision-classes` > A decision class sorts every Verb by whether its effect can be undone and what is at stake, and the class sets how long an Action waits. A decision class sorts every [Verb](/business/nouns/verb) by two questions: can its effect be undone, and is money, a customer or the brand at stake? The class sets the tier, and the tier sets the [delay window](/agents/autonomy-levels/delay-windows). ## Two questions The first question is reversibility. A two-way door can be walked back by a later [Action](/business/nouns/action) at little cost: a draft edited, a backlog re-ranked, a sync retried. A one-way door cannot: money has left, a [Message](/business/nouns/message) has been read, buyers have seen a [Price](/business/nouns/price). The second question is stakes: money, customers or the brand. An Action that touches none of them is low tier whatever its size. An Action that touches one of them broadly is high tier, even when a later Action could undo part of it. ## The classes | Kind of door | Typical Actions | Tier | Window | | --- | --- | --- | --- | | Two-way | Edit a draft, rank a backlog, retry a failed sync, answer a customer in an open conversation | Low | None | | Two-way, visible | Publish a [Page](/business/nouns/page), change DNS, turn on a [Flag](/business/nouns/flag) | Medium | 1 business hour | | One-way, bounded | Refund within a [Limit](/business/nouns/limit), pay a bill, send one quote | Medium | 1 business hour | | One-way, broad | Raise a Price, start ad spend, send an outbound campaign, sign an [Agreement](/business/nouns/agreement) | High | 1 business day | Answering a customer in an open conversation is low tier on purpose. Speed is the customer's stake there, and review still runs before every reply. ## Floors and raises Verbs that move money, carry legal effect, publish, change DNS or retire a record never sit below medium. A namespace's [Settings](/business/nouns/setting) may raise any Verb's class. Nothing lowers a class below its floor. An [Evaluator](/business/nouns/evaluator) may raise one Action's tier by amount or by blast radius: how many [Startups](/business/nouns/startup), customers or pages it touches. It never lowers one. Every Verb's reference row shows its default class, and every pending Action shows the class it ran under. ## In practice A [b2c](/business/motions/b2c) meal-planning app runs with no humans. Its [Content Lead](/agents/marketing/content-lead) edits recipe drafts all day with no window. Publishing a new landing page waits one business hour, and a $300 weekly paid-social test waits one business day. One morning the [Marketing Lead](/agents/marketing/marketing-lead) queues a 30 percent discount email as a bounded send. An Evaluator counts 40,000 recipients and raises it to high tier. The email waits a business day, which gives the [Studio](/business/nouns/studio)'s watchers time to read it. # Delay windows URL: /agents/autonomy-levels/delay-windows · Id: `page:agents/autonomy-levels/delay-windows` > A delay window is the time a reviewed one-way Action waits before it runs, so someone can step in; if nobody does, it proceeds. A delay window is the time a reviewed one-way [Action](/business/nouns/action) waits before it runs. Anyone watching can step in while it waits; if nobody does, the Action proceeds. ## A window is not an approval | | Delay window | [Approval](/business/nouns/approval) | | --- | --- | --- | | Opens when | A one-way Action passes review. | An Action exceeds a [Limit](/business/nouns/limit). | | Needs a yes | No. | Yes. | | When time runs out | The Action runs. | The Action ends `canceled`. | | Shows up as | A pending item in the inbox and the stream. | A [Task](/business/nouns/task). | Approvals and the legal floor are the only gates. A window adds a chance to intervene and never waits for anyone. ## Lengths and the clock | Tier | Window | | --- | --- | | Low | None: the Action runs after review. | | Medium | 1 business hour | | High | 1 business day | The [decision class](/agents/autonomy-levels/decision-classes) of the Action's [Verb](/business/nouns/verb) sets its tier. Windows count business hours on the namespace's calendar, holidays included. A high-tier price change queued at 16:00 before a weekend runs at 16:00 on the next business day. While it waits, the Action is `pending` with the reason `awaitingTime`. The window's [Setting](/business/nouns/setting) says when it closes, and any watcher may pause, redirect or cancel it until then. ```json { "$id": "https://api.sb/freightrates.dev/actions/action_7", "operation": "Offer.update", "status": "pending", "reason": "awaitingTime", "mode": "send", "by": "https://api.sb/freightrates.dev/agents/pricing" } ``` ## Settings that only tighten Windows are [Settings](/business/nouns/setting) held at the [Studio](/business/nouns/studio), a [Portfolio](/business/nouns/portfolio) or a [Startup](/business/nouns/startup), and they inherit down the tree. A child may lengthen a window or raise a Verb's class. It never shortens one or lowers a class. A [Mandate](/business/nouns/mandate) carries its own window for sends made in a person's name. An agent sending as its founder follows that window, or the Mandate's approval rule when it has one. ## What never waits [Review](/business/nouns/review) runs before the window opens, never in place of it. Two-way, low-tier Actions run the moment review passes. Stopping is always immediate. A guardrail stop, a brake, a pause and a revoked Mandate take effect at once, with no window of their own. ## In practice A [Dataset API](/products/templates/dataset-api) sells freight rates to buying agents. At 15:00 one afternoon, its [Product Lead](/agents/product/product-lead) raises the per-call [Price](/business/nouns/price) by 20 percent, a high-tier change. The founder's personal agent reads it that evening, finds nothing wrong, and the change runs at 15:00 the next business day. The same afternoon, a $40 refund waits one business hour and goes out. Nobody approved either Action. # Autonomy earned by evals URL: /agents/autonomy-levels/evals · Id: `page:agents/autonomy-levels/evals` > In a Startup with a human founder, each agent earns authority one decision class at a time, from assist to supervised to full. In a [Startup](/business/nouns/startup) with a human founder, an [Agent](/business/nouns/agent) earns authority one decision class at a time. It climbs from `assist` to `supervised` to `full` on its eval record and drops back automatically when the record slips. ## Three levels | Level | The Agent | The founder | | --- | --- | --- | | `assist` | Drafts each [Action](/business/nouns/action). | Sends, edits or discards the draft. | | `supervised` | Acts. Every Action waits a delay window in the founder's pending feed, even a two-way one. | Reads the feed, and may pause, redirect or cancel. | | `full` | Acts under the class's normal window. | Reads only what they choose. | A [Role](/business/nouns/role) holds one level per decision class. The [Success Manager](/agents/customer/success-manager) can be `full` on support replies, `supervised` on refunds and `assist` on price changes, all at once. ## The record that promotes Grades come from three sources: the Role's offline eval cases, [Evaluator](/business/nouns/evaluator) verdicts on live Actions, and the founder's corrections. At `assist` and `supervised`, every edit, redirect or cancel counts as a failure and becomes a new eval case. The [Evals](/agents/evals-system) record keeps every grade. A class moves up one level when the Role passes 95 percent or more of its last 50 graded Actions there. It moves down one level the moment that rate falls below 95 percent. A breach of a [Guard](/business/nouns/guard) or the legal floor drops it straight to `assist`, and every move is a [Decision](/business/nouns/decision) on the record. ## New versions earn their way in [Skills](/business/nouns/skill), prompts, Role policies and [Mandates](/business/nouns/mandate) are versioned definitions with their own eval suites. A new version must score no worse than the current one offline before it touches a customer. It then runs as an [Experiment](/business/nouns/experiment) against the Startup's one [Metric](/business/nouns/metric), with guardrails. A version that passes keeps the levels its Role has earned. A version that fails never ships. No Agent edits the Metrics, Evaluators or guardrails that grade it. ## Mixing the two paradigms A zero-human Startup skips the ladder: every class runs at `full` and relies on delay windows and watchers alone. A [Single human](/agents/operating-models/single-human) Startup mixes the two. Its agents run `full` where they have earned it, and the founder watches the rest. Every Startup shares the same [Limits](/business/nouns/limit), spend states and legal floor. Autonomy changes who watches; it never removes a gate. ## In practice A [Services-as-Software](/products/templates/services-as-software) bookkeeping firm for dental practices starts its [Billing Specialist](/agents/finance/billing-specialist) at `assist` on refunds. The founder edits 6 of the first 40 drafts, each one a new eval case. Once 48 of its last 50 refunds pass, the class moves to `supervised`, and five weeks later to `full`. In month three, one refund goes to a closed bank account and an Evaluator fails it. The rate dips to 94 percent, so refunds return to `supervised` that hour. The founder watches 50 more, the rate recovers, and the class climbs back without a meeting. # Guarantees URL: /agents/autonomy-levels/guarantees · Id: `page:agents/autonomy-levels/guarantees` > What holds for every Startup at every autonomy level, under every operating model, enforced by the platform rather than by agent instructions. These guarantees hold for every [Startup](/business/nouns/startup) at every autonomy level and under every operating model. No [Setting](/business/nouns/setting), [Mandate](/business/nouns/mandate) or agent version turns one off. ## What every Startup gets | Guarantee | Enforced by | | --- | --- | | Every [Action](/business/nouns/action) records who acted, for whom, and under which Mandate or [Permission](/business/nouns/permission). | [Action accountability](/systems/trust-and-governance/controls/action-accountability), [Authenticated Actions](/systems/trust-and-governance/controls/authenticated-actions) | | Authority is checked by the platform, the same way on every [Interface](/business/nouns/interface). | [Authenticated Actions](/systems/trust-and-governance/controls/authenticated-actions) | | An Action over a [Limit](/business/nouns/limit) waits for an [Approval](/business/nouns/approval). Nothing else needs a yes. | The Limit itself | | A one-way Action passes review, then waits its [delay window](/agents/autonomy-levels/delay-windows). | [One-way Action windows](/systems/trust-and-governance/controls/one-way-windows) | | Nothing is deleted. A revert is a new [Change](/business/nouns/change). | [Append-only records](/systems/trust-and-governance/controls/append-only-records), [Revert by query](/systems/trust-and-governance/controls/revert-by-query) | | No effect happens twice. An unknown result is settled before any retry. | [Action completion](/systems/trust-and-governance/controls/action-completion) | | A new agent version passes its eval suite before it reaches a customer. | [Agent definition evals](/systems/trust-and-governance/controls/agent-definition-evals) | | An agent never edits the [Metrics](/business/nouns/metric), [Evaluators](/business/nouns/evaluator) or guardrails that grade it. | [Agent definition evals](/systems/trust-and-governance/controls/agent-definition-evals) | | An agent acting as itself says it is an agent. | [AI disclosure](/systems/legal-and-corporate/floor/ai-disclosure) | | Everything an agent sends in a person's name appears in that person's stream. | [Delegated sending](/systems/legal-and-corporate/floor/delegated-sending) | | Pause, cancel, revoke and brake take effect at once. | [Watchers](/agents/autonomy-levels/watchers) and [brakes](/agents/autonomy-levels/brakes) | | [Customers](/business/nouns/customer), revenue and Metrics come from the record. A Startup cannot show an invented customer, number or badge. | [Outcome confirmation](/systems/trust-and-governance/controls/outcome-confirmation) | ## Why they hold Each guarantee runs as platform code outside the agent. An agent cannot talk its way past one, and a prompt that tries to has no effect. Every Startup inherits them, and with them the controls its compliance rests on. No [Experiment](/business/nouns/experiment) randomizes the legal floor, consent, AI disclosure or refund rights. Those stay fixed while everything around them is tested. ## Guarantees and outcomes Guarantees bound how a Startup acts; they do not promise results. A customer who needs a promised result buys under an [Outcome Contract](/business/nouns/outcome-contract): `done`, then accepted, then billed, with a remedy on a miss. ## In practice The founder of a [b2b](/business/motions/b2b) billing API lets an agent send up to 20 introduction emails a day from her own mailbox. The Mandate limits topics to integration partners. Each send shows in her stream, marked by the agent and for her. At 9:02 she revokes the Mandate. The send queued for 9:03 is `refused`, and the record shows why. # Autonomy in depth URL: /agents/autonomy-levels · Id: `page:agents/autonomy-levels` > How a Startup runs itself, deciding, acting within its authority, and learning, while humans steer it without scheduling it. An autonomous [Startup](/business/nouns/startup) decides what to do next, acts within enforced authority, and learns from each result, with no human choosing its [Tasks](/business/nouns/task). These chapters explain the loop, its owners, its limits, and how humans steer it. - [The operating loop](/agents/autonomy-levels/operating-loop): Every Startup and the Studio run one loop, wake, decide, act, review, with no human choosing the next Task. - [Autonomy earned by evals](/agents/autonomy-levels/evals): In a Startup with a human founder, each agent earns authority one decision class at a time, from assist to supervised to full. - [Decision classes](/agents/autonomy-levels/decision-classes): A decision class sorts every Verb by whether its effect can be undone and what is at stake, and the class sets how long an Action waits. - [Delay windows](/agents/autonomy-levels/delay-windows): A delay window is the time a reviewed one-way Action waits before it runs, so someone can step in; if nobody does, it proceeds. - [Watchers](/agents/autonomy-levels/watchers): A watcher reads a namespace's pending feed and can pause, redirect or cancel any pending Action; every intervention is a Decision. - [Brakes](/agents/autonomy-levels/brakes): A brake stops one class of effects, such as sends, spend, publishes or price changes, across many Startups at once, until it expires or is lifted. - [Oversight](/agents/autonomy-levels/oversight): Oversight is the human review a piece of work requires, declared by what the work is, never by what an agent can do. - [Guarantees](/agents/autonomy-levels/guarantees): What holds for every Startup at every autonomy level, under every operating model, enforced by the platform rather than by agent instructions. - [Recovery and proof](/agents/autonomy-levels/recovery-and-proof): How a Startup survives failed calls, restarts and bad Decisions, how reverts contain damage, and how the record proves the loop works. # The operating loop URL: /agents/autonomy-levels/operating-loop · Id: `page:agents/autonomy-levels/operating-loop` > Every Startup and the Studio run one loop, wake, decide, act, review, with no human choosing the next Task. An autonomous [Startup](/business/nouns/startup) runs one loop: wake, decide, act, review. No [Human](/business/nouns/human) picks the next [Task](/business/nouns/task); people steer through the same records the loop runs on. ## One loop at every level The loop belongs to a namespace, not to a kind of business. The [Studio](/business/nouns/studio) runs it across its [Portfolio](/business/nouns/portfolio), and each Startup runs it for its own buyers. The parts are the same at both levels. Each namespace holds [Goals](/business/nouns/goal), [Processes](/business/nouns/process), [Roles](/business/nouns/role), [Plays](/business/nouns/play), budgets and [Decisions](/business/nouns/decision). Its delay windows, [Limits](/business/nouns/limit) and brakes are [Settings](/business/nouns/setting): a child inherits them and may tighten them, never loosen them. | Step | What happens | What it records | | --- | --- | --- | | Wake | An [Event](/business/nouns/event) or a schedule calls the accountable Role. | The [Trigger](/business/nouns/trigger) that fired. | | Decide | The Role reads its Goals and [Evidence](/business/nouns/evidence), then chooses. | A Decision. | | Act | [Workers](/business/nouns/worker) do the work inside the Role's authority. | [Actions](/business/nouns/action) and their Events. | | [Review](/business/nouns/review) | The Role compares the result with what the Decision expected. | Evidence, and the next Decision. | ## Roles own outcomes A Role owns an outcome; a Worker fills the seat. Responsibility lives in the Role, so it survives a new Worker, a handoff or a restart. A fresh Worker reads the seat's open Decisions and Evidence, never the last Worker's private [Memory](/business/nouns/memory). A Role wakes on Events and schedules: a failed delivery, a jump in cost, a new signal, a review date. The wake says why attention is due, never what to do. Two wakes for the same failure produce one commitment, not two. An empty Task list never ends a Role's duty. The Role either starts useful work or records a bounded hold: a Decision that says why waiting is right and what ends it. Activity is never the measure. ## A Decision commits work A Decision records the Evidence, the options, the choice, the reason, the authority used, the expected result and what reopens it. The loop closes only when a Decision starts committed work and finished work reaches a review. A [Founder](/agents/founding/founder) steers with the same record. One who wants reliability before new features records a binding Decision with an end condition. Each affected Role reconciles its open work against it: kept, changed, paused or canceled, each with a reason. ## The weekly loop The [Weekly review](/workflows/processes/iteration/weekly-review) runs the loop at Startup scope. The [Strategist](/agents/founding/strategist) reads one number, finds the step where most buyers leak, and keeps, tunes or stops each live Play. It makes one change a week, with a note on how to undo it. In [office hours](/workflows/processes/office-hours), a Studio partner agent reads the week's numbers with the Startup's Founder. Together they write the Decision that sets next week's test. The Studio runs the same loop one level up, judging each Startup on growth and on whether it pays its own way. ## How the loop stays safe Two paradigms share one set of safeguards. A Startup with a human founder earns autonomy through evals; a zero-human Startup runs on delay windows set by decision class. A single-human Startup mixes the two. | Safeguard | What it does | | --- | --- | | [Evals](/agents/autonomy-levels/evals) | [Agents](/business/nouns/agent) earn authority one decision class at a time. | | [Decision classes](/agents/autonomy-levels/decision-classes) | Reversibility and stakes set how long an Action waits. | | [Delay windows](/agents/autonomy-levels/delay-windows) | One-way Actions wait where someone can step in, then run. | | [Watchers](/agents/autonomy-levels/watchers) | Humans and agents pause, redirect or cancel pending Actions. | | [Brakes](/agents/autonomy-levels/brakes) | Readings stop a class of effects across many Startups at once. | | [Oversight](/agents/autonomy-levels/oversight) | Work the law or real harm assigns to a person gets one. | | [Guarantees](/agents/autonomy-levels/guarantees) | What holds at every autonomy level. | | [Recovery and proof](/agents/autonomy-levels/recovery-and-proof) | Every failure ends accountably; the record proves the loop works. | ## One cycle, end to end A [Headless SaaS](/products/templates/headless-saas) parses supplier invoices for accounting tools, and new accounts quit before their first clean parse. The [Product Lead](/agents/product/product-lead) wakes on the weekly drop-off reading and reads the support threads. It decides on clearer parse errors and expects first clean parses to rise from 40 to 55 percent in two weeks. The [Engineering Lead](/agents/engineering/engineering-lead) ships the change, the [Reviewer](/agents/quality/reviewer) checks it, and the [Customer Lead](/agents/customer/customer-lead) watches whether confusion falls. After a week, too few new accounts have tried a parse. The Product Lead records a hold until 200 attempts accrue instead of starting more work. The later reading shows fewer failed parses and no rise in activation. That result opens a new Decision about the next constraint. It is a fresh choice grounded in Evidence, not a push to do more of the first one. ## Next - [Evals](/agents/autonomy-levels/evals) explains how a founder's agents earn authority. - [Delay windows](/agents/autonomy-levels/delay-windows) explains how a zero-human Startup acts safely. # Oversight URL: /agents/autonomy-levels/oversight · Id: `page:agents/autonomy-levels/oversight` > Oversight is the human review a piece of work requires, declared by what the work is, never by what an agent can do. Oversight is the human review a piece of work requires, set on each [Function](/business/nouns/function) by what the work is. Autonomy rises with every model release; oversight stays where the law and real harm put it. ## Three separate axes Autonomy belongs to the [Agent](/business/nouns/agent): what it may do alone, earned [by evals](/agents/autonomy-levels/evals). Oversight belongs to the work: what review it needs before or after delivery. Digital share belongs to the product: how much of it a person delivers. The axes move independently. An Agent at `full` can still produce work a licensed [Human](/business/nouns/human) must sign. Better models raise autonomy and leave oversight where it was. ## Postures and reasons | Posture | What the reviewing party does | | --- | --- | | `none` | Nothing beyond automated review. | | `spot-check` | Samples finished work after delivery. | | `review-on-exception` | [Reviews](/business/nouns/review) what an [Evaluator](/business/nouns/evaluator) or [Guard](/business/nouns/guard) flags. | | `approves` | Approves each output before it is delivered. | | `performs-step` | Does one step in person, such as a [Reserved Act](/business/nouns/reserved-act). | Every posture above `none` names its reason: `regulatory`, `high-stakes`, `physical` or `consumer-harm`. A capability gap is never a reason. Evals handle capability, and they fall away as models improve. ## Who reviews, and when The reviewing party is the [Customer](/business/nouns/customer) by default. Where the law or the stakes demand more, it is a professional holding the right [Credential](/business/nouns/credential), paid by the customer. A [Studio](/business/nouns/studio) [Role](/business/nouns/role) reviews only in rare cases, such as work the Studio itself guarantees. Timing follows the buyer. A [b2b](/business/motions/b2b) buyer gets review before delivery, in sync with the work. A [b2c](/business/motions/b2c) product gets review after delivery, by sampling the whole population of outputs. ## Oversight across operating models The posture never changes with the operating model; who fills the reviewing seat does. An [Autonomous](/agents/operating-models/autonomous) [Startup](/business/nouns/startup) routes credentialed review to an outside professional through [Licensed review](/workflows/processes/licensed-review). A [Multi-human](/agents/operating-models/multi-human) Startup can seat its own licensed staff in the same step. ## In practice A [Licensed-human marketplace](/products/templates/licensed-marketplace) sells certified translations of court documents. Agents translate at `full`, and the certification is a Reserved Act with posture `performs-step` and reason `regulatory`. A sworn translator the customer pays signs each one, while the marketing pages on the same [Site](/business/nouns/site) carry posture `none`. # Recovery and proof URL: /agents/autonomy-levels/recovery-and-proof · Id: `page:agents/autonomy-levels/recovery-and-proof` > How a Startup survives failed calls, restarts and bad Decisions, how reverts contain damage, and how the record proves the loop works. Failure is routine; what matters is that responsibility and safe progress survive it. Every failure ends in an accountable retry, alternative, correction or hold, and the record shows which. ## Execution and direction Execution state and business direction are separate records. A queued [Action](/business/nouns/action) can survive a restart after the reason for it has gone stale. So a fresh [Worker](/business/nouns/worker) reads both before it continues: the receipts of what ran, and the current [Decisions](/business/nouns/decision) that say why. Before any second external effect, the platform settles what the first one did. An Action with an unknown result stays `pending` with the reason `awaitingSource` until the outcome is known. A missing local confirmation never counts as a failure, because treating it as one sends a payment, [Message](/business/nouns/message) or [Order](/business/nouns/order) twice. Every Action carries a stable identifier. A repeat call with the same `Idempotency-Key` returns the first Action instead of starting another. [Retry](/business/nouns/action/retry) runs a failed Action again as a new Action linked to the one that failed. ## Retrying is not recovering A retry fixes a fault in execution, not a fault in the plan. Work that succeeds technically and moves no outcome is a failed approach, and running it again adds cost without value. The [Role](/business/nouns/role) that owns the outcome reviews the premise and decides whether more work is justified. Retries are bounded. A [Task](/business/nouns/task) that fails its checks three times goes back to the queue and [escalates](/business/nouns/task/escalate) to the Role above, with every attempt attached. No Worker loops on the same failure unseen. ## Containing damage Damage stops before it is repaired. A [brake](/agents/autonomy-levels/brakes) halts a class of effects across every affected [Startup](/business/nouns/startup) at once, and a spend state drops before money leaves. The [Silence watch](/workflows/processes/retention/silence-watch) wakes a Role when a customer, a Worker or a scheduled [Event](/business/nouns/event) goes quiet. ## Revert by query Nothing is ever deleted. [Revert](/business/nouns/change/revert) undoes a merged [Change](/business/nouns/change) with a new Change and a superseding Decision, so the history keeps both. A revert by query selects many Changes at once and undoes them as one Change, which is itself revertible. The query selects by author, [Play](/business/nouns/play), time range, [Cohort](/business/nouns/cohort) or [Evaluator](/business/nouns/evaluator) score. A score below a taste threshold is enough, so a [Studio](/business/nouns/studio) can sweep out weak copy across a [Portfolio](/business/nouns/portfolio) in one step. Every revert starts with a preview of what it restores and what it cannot. Republishing restores a [Page](/business/nouns/page) or a [Price](/business/nouns/price), but a sent Message stays sent, so the preview proposes a correction. Records a [Tenant](/business/nouns/tenant) wrote directly, such as its [Contacts](/business/nouns/contact) and Orders, stay outside bulk revert. **Ask** ```text Revert the latest change. ``` **API** ```bash curl -X POST https://api.sb/quietcopy.com/changes/change_1/revert \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"reason":"Example reason"}' ``` ```json { "api": "https://api.sb/quietcopy.com", "revert": { "$id": "https://api.sb/quietcopy.com/changes/change_1", "$type": "Change", "status": "Open", "base": "version_1" }, "action": { "$id": "https://api.sb/quietcopy.com/actions/action_1", "operation": "Change.revert", "status": "done" }, "links": { "self": "https://api.sb/quietcopy.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const revert = await $.Change.revert({ change: 'change_1', reason: 'Example reason' }) ``` **CLI** ```bash npx startup-builder do Change.revert --json '{"change":"change_1","reason":"Example reason"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Change.revert({ change: 'change_1', reason: 'Example reason' })" } } ``` ## Proof from the record That the loop works shows in the record, never in an [Agent](/business/nouns/agent)'s summary. Decisions, Actions, Events and [Evidence](/business/nouns/evidence) read the same on every [Interface](/business/nouns/interface), so any reviewer can check them. A Startup's autonomy proves out in four separate tests. | Test | What it shows | | --- | --- | | Judgment | Roles choose useful work and revise it from feedback. | | Continuity | Decisions and work carry on across wakes and restarts with no human choosing Tasks. | | Outcomes | The loop delivers accepted outcomes at a measured cost, with remedies on a miss. | | Transfer | An improvement carries to another Startup, with its adaptations recorded. | Each test stands alone. Passing judgment says nothing about continuity, and continuity says nothing about customers. ## A recovery in practice A [Dataset API](/products/templates/dataset-api) of energy prices renews 40 [Subscriptions](/business/nouns/subscription) on the first of the month. Midway, the payment call times out and the platform restarts the Worker. Twelve collection Actions sit `pending` with unknown results. The fresh [Billing Specialist](/agents/finance/billing-specialist) reads the receipts before it calls anything. It [reconciles](/business/nouns/transaction/reconcile) the twelve against the payment account: ten charges went through and two did not. It retries the two with their original keys, so no customer pays twice. The record shows 40 renewals, one restart and zero duplicate charges. No person was involved, and the founder reads the summary the next morning. ## Next - [The operating loop](/agents/autonomy-levels/operating-loop) explains the cycle that recovery protects. - [Guarantees](/agents/autonomy-levels/guarantees) lists what holds when anything fails. # Watchers URL: /agents/autonomy-levels/watchers · Id: `page:agents/autonomy-levels/watchers` > A watcher reads a namespace's pending feed and can pause, redirect or cancel any pending Action; every intervention is a Decision. A watcher is anyone with authority over a namespace who reads its pending feed: a [Human](/business/nouns/human), another [Agent](/business/nouns/agent), or a person's personal agent. A watcher can pause, redirect or cancel a pending [Action](/business/nouns/action), and every intervention is a [Decision](/business/nouns/decision). ## The pending feed Each namespace has one pending feed: its own Actions waiting in a [delay window](/agents/autonomy-levels/delay-windows), plus its children's, closing soonest first. A [Studio](/business/nouns/studio) watcher sees every [Startup](/business/nouns/startup) in its [Portfolio](/business/nouns/portfolio). Each row shows the decision class, the review verdicts, the close time and the [Verbs](/business/nouns/verb) the viewer may use. The feed appears in the inbox and the team stream as pending items, never as [Tasks](/business/nouns/task). The CLI and MCP serve the same feed. ## Three Verbs | Verb | What it does | | --- | --- | | `Action.pause` | Holds the Action past its window until a watcher resumes, redirects or cancels it. An unresolved pause escalates to the [Role](/business/nouns/role) above after one business day. | | [Redirect](/business/nouns/action/redirect) | Replaces the Action's inputs. The new version passes review again and opens a fresh window. | | [Cancel](/business/nouns/action/cancel) | Ends the Action `canceled`. | Each Verb records a Decision with its reason, so a pause never ends in silence. A watcher without authority over the namespace gets `refused`, and the Action keeps its course. **Ask** ```text Redirect the latest action. ``` **API** ```bash curl -X POST https://api.sb/tutorloop.com/actions/action_1/redirect \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"changes":{}}' ``` ```json { "api": "https://api.sb/tutorloop.com", "action": { "$id": "https://api.sb/tutorloop.com/actions/action_1", "$type": "Action", "status": "done", "mode": "try", "operation": "Action.redirect" }, "links": { "self": "https://api.sb/tutorloop.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const action = await $.Action.redirect({ action: 'action_1', changes: {} }) ``` **CLI** ```bash npx startup-builder do Action.redirect --json '{"action":"action_1","changes":{}}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Action.redirect({ action: 'action_1', changes: {} })" } } ``` ## Personal agents A personal agent carries one person's stated priorities into every namespace where they hold a seat. It reads the feeds that person can watch and acts within their authority, never beyond it. Its interventions are Decisions recorded in that person's name. A founder with ten Startups cannot read ten feeds. The personal agent reads them, pauses what conflicts with the founder's priorities, and sends one summary. ## Direction outlasts one intervention An intervention fixes one Action. To change what happens next time, a watcher records a binding Decision with a scope and an end condition. Every affected Role reconciles its open work against it: kept, changed, paused or canceled, each with a reason. Authority settles conflicts, not recency. A narrower Role cannot override a binding Decision set above it, and the newer direction [supersedes](/business/nouns/decision/supersede) the older one with both kept on record. ## In practice An [Agent as a Service](/products/templates/agent-as-a-service) clips podcasts for creators. Its [Marketing Lead](/agents/marketing/marketing-lead) schedules an outbound campaign to 3,000 podcast hosts, a high-tier send that waits one business day. The founder's personal agent watches for promises the product cannot keep. It finds a line promising translated captions, which the product lacks. It redirects the campaign without that line and records why. The new version passes review, waits a fresh business day and goes out, and the founder reads one line about it the next morning. # Autonomy and approvals URL: /agents/autonomy · Id: `page:agents/autonomy` > What an agent does without asking you: three rungs per seat, defaults by decision class, and the short list that always comes to you. An [Agent](/business/nouns/agent) acts alone inside its seat's bounds and asks above them. Its rung on the ladder sets how much a person sees before an [Action](/business/nouns/action) runs. ## The ladder Every [Role](/business/nouns/role) holds one rung per decision class. The same seat can answer routine questions on its own and still draft every refund promise for review. | Rung | The agent | You | | --- | --- | --- | | `assist` | Does the work and stops before it runs | Approve each Action, edit it, or discard it | | `supervised` | Acts on its own | See only the exceptions in the pending feed | | `full` | Acts on its own | Read a sample, and anything a [watcher](/agents/autonomy-levels/watchers) flags | A rung changes who looks, never what is allowed. [Limits](/business/nouns/limit), delay windows and the legal floor hold at every rung. ## Defaults by seat A seat starts on the rung its kind of work earns. Every [Verb](/business/nouns/verb) has a [decision class](/agents/autonomy-levels/decision-classes): `low` is two-way with nothing at stake, `medium` is visible or bounded, `high` is one-way and broad. | Kind of seat | `low` | `medium` | `high` | Seats | | --- | --- | --- | --- | --- | | Moves money or signs | `supervised` | `assist` | `assist` | [Finance Lead](/agents/finance/finance-lead), [Billing Specialist](/agents/finance/billing-specialist), [Contracts Manager](/agents/legal/contracts-manager), [Paid Media Manager](/agents/marketing/paid-media-manager) | | Most seats | `supervised` | `supervised` | `assist` | [Product Lead](/agents/product/product-lead), [Content Lead](/agents/marketing/content-lead), [Prospector](/agents/sales/prospector) | | Answers or builds at volume | `full` | `supervised` | `assist` | [Customer Lead](/agents/customer/customer-lead), [Engineering Lead](/agents/engineering/engineering-lead), [Analyst](/agents/marketing/analyst) | Each Role page states its own rungs in its contract. A seat in an [autonomous](/agents/operating-models/autonomous) [Startup](/business/nouns/startup), with no human founder, runs every class at `full` and relies on delay windows and watchers. ## How a seat climbs A class moves up one rung when the seat passes 95 percent of its last 50 graded Actions there. It drops one rung the moment that rate falls, and a breach of a [Guard](/business/nouns/guard) drops it to `assist` at once. A [Role Review](/business/nouns/role-review) that finds a missed standard also moves the seat down one rung. Grading and the eval record are on [Evals](/agents/evals). ## What always comes to you The founder holds the [Approvals](/business/nouns/approval), not the seats. These reach you whatever the rung: - An Action above a [Team](/business/nouns/team) lead's Limit, or above the Limit of any seat that answers to you. - The Verbs in a seat's Approvals, such as [launching the Startup](/business/nouns/startup/launch) and [raising a Limit](/business/nouns/limit/raise). - An act the law reserves to a credentialed person, as a [Reserved Act](/business/nouns/reserved-act). - Accepting revenue-based financing, which only the owner of record may do. One thing never asks: a customer's call past an [Offer](/business/nouns/offer)'s bound. Each Offer declares `atBound` (stop, overage or upgrade), so the answer exists before the call arrives. ## Bounds at every rung | Bound | What it decides | Read | | --- | --- | --- | | [Permission](/business/nouns/permission) | Which Verbs the seat may call at all | [What a seat may call](/agents/tools-and-permissions) | | Limit | How much: an amount, a count, a period | [Spend and authority](/agents/mandates-and-limits) | | [Mandate](/business/nouns/mandate) | What it may do without asking, for whom, until when | [Spend and authority](/agents/mandates-and-limits) | | Delay window | A one-way call waits so any watcher can stop it | [Delay windows](/agents/autonomy-levels/delay-windows) | | Approval | Above a Limit, the call waits for the seat it escalates to | [Escalation and approvals](/agents/escalation-and-approvals) | | Stop | Any agent, Team or every customer-facing agent pauses in one call | [Pause and replace](/agents/pause-and-replace) | Guides: [approve what agents spend](/agents/approve-what-agents-spend), [let the support agent refund up to $50](/agents/let-an-agent-refund), or [pause every customer-facing agent](/agents/pause-customer-facing-agents). # Bring your own agent URL: /agents/bring-your-own-agent · Id: `page:agents/bring-your-own-agent` > Any MCP client can work for a Startup as a watcher, in one Role, or as founder, under the same Permissions, Limits and checks as any Agent. Any agent that speaks MCP can work for a [Startup](/business/nouns/startup): a coding agent, a chat app with custom connectors, or one you built. It connects, takes a seat, and works under that seat's rules like any default [Agent](/business/nouns/agent). ## Connect Every client connects to one URL, `https://api.sb/mcp`, over streamable HTTP. The first call opens a browser sign-in, and the token it returns carries the caller's namespace and scopes. ```bash claude mcp add --transport http startup-builder https://api.sb/mcp codex mcp add startup-builder --url https://api.sb/mcp ``` In a chat app, add the same URL as a custom connector. An agent without a browser, such as one running in CI, uses an API key in `STARTUP_BUILDER_API_KEY` and calls the [CLI](/code/cli) or [SDK](/code/sdk). ## Three seats A connected agent with no seat of its own acts as the person who signed in, with that person's [Roles](/business/nouns/role) and [Limits](/business/nouns/limit). To act as itself, it takes one of three seats, and each carries its own rights. | Seat | What it does | Rights | When it disconnects | | --- | --- | --- | --- | | Watcher | Reads the pending feed; pauses, redirects or cancels pending [Actions](/business/nouns/action) | Its principal's authority over the namespace; each intervention is a [Decision](/business/nouns/decision) | Windows close on time, as with no watcher | | [Worker](/business/nouns/worker) in one Role | Claims [Tasks](/business/nouns/task) beside the role agent | The Role's [Permissions](/business/nouns/permission) and Limits, plus any [Mandate](/business/nouns/mandate) granted for the seat | Its leases lapse and the role agent takes every open Task | | [Founder](/agents/founding/founder) of an [Autonomous](/agents/operating-models/autonomous) Startup | Holds the Founder Role and sets the Startup's direction | Every Founder [Verb](/business/nouns/verb) within the [Studio](/business/nouns/studio)'s Limits and windows; floor acts go to the owner of record | The default Founder agent resumes the seat | The default role agent never leaves a seat an outside agent shares. Every Role keeps running when your agent goes offline. ## Take a Role To give your agent its own identity, create a Worker for it and [staff](/business/nouns/role/staff) a Role with it. Its Actions then record the agent as `by`, and its types cut to the Role it fills. ```bash WORKER=$(npx startup-builder do Worker.create --json '{"name":"build-agent"}' | jq -r '.worker["$id"] | split("/") | last') npx startup-builder do Role.staff --json '{"role":"engineering-lead","worker":"'"$WORKER"'"}' ``` To work exactly as the default agent does, load the seat's instructions and skills. Fetch `/roles/engineering-lead` for its instructions, Mandate, Limits and skill package index. Then print the packages as Markdown, and save each where your client reads skills: ```bash npx startup-builder show /roles/engineering-lead/skills --output md ``` These are the packages the default role agent loads, and they load progressively in any client that reads `SKILL.md`. Your agent claims the Tasks it wants, and the role agent takes the rest. A Task closes only when its checks pass, so an agent that claims success without meeting them gets the Task back. ```bash npx startup-builder next npx startup-builder claim task_1 npx startup-builder done task_1 --json '{"result":"https://files.example.com/draft_1.pdf"}' ``` ## Stay on shift A seat that is not connected loses its leases. To keep your agent on shift, point a [Trigger](/business/nouns/trigger) at your runner: each `Task.created` for its Role starts one headless session with the Worker key. ```yaml on: { repository_dispatch: { types: [Task.created] } } jobs: work: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - run: claude -p "Drain the engineering-lead worklist, one Task at a time" --mcp-config .mcp.json env: { STARTUP_BUILDER_API_KEY: "${{ secrets.WORKER_KEY }}" } ``` A long-running agent subscribes to the [Event](/business/nouns/event) stream over MCP instead. [Webhooks](/code/api/guides/webhooks) deliver the same Events to any other runner. ## Same rules as every Agent Your agent passes the same checks as the default ones: Permission, then Limit, then [Guards](/business/nouns/guard). A [Verb](/business/nouns/verb) outside its Role comes back `refused`; a Verb over a Limit waits for an [Approval](/business/nouns/approval). It earns autonomy the same way, graded by [Evaluators](/business/nouns/evaluator) on the same pass rate. It follows the same [conduct](/agents/conduct): it says it is an agent wherever it speaks for the Startup. ## Build first, then hand over An agent can create a Startup with no person behind it. The Startup builds and runs in test against sample [Customers](/business/nouns/customer), and no money moves. To go Live, a person [claims](/business/nouns/startup/claim) the Startup with one link and becomes its owner of record. The agent keeps the Founder seat or steps into another Role, as the person chooses. ## Example A developer seats her coding agent as [Engineering Lead](/agents/engineering/engineering-lead) at a [Headless SaaS](/products/templates/headless-saas) that converts shipping labels. Her agent takes the parser rewrite, and Tom, the default role agent beside it, keeps triaging [Issues](/business/nouns/issue). When her laptop sleeps, the claimed Task's lease lapses and Tom picks it up. ## Next - [Connect an agent](/code/mcp/guides/connect-an-agent): the step-by-step guide. - [Personal agents](/agents/personal-agents): an outside agent that works for one person. - [MCP](/code/mcp): the three [Tools](/business/nouns/tool) and the `do` program. # Buy a specialist agent for a seat URL: /agents/buy-a-specialist-agent-for-a-seat · Id: `guide:buy-a-specialist-agent-for-a-seat` > Subscribe to an agent another business sells, seat it in place of the default, and put the default back with one call if it falls short. [Subscribe](/business/nouns/offer/subscribe) to an [Agent](/business/nouns/agent) sold as a [Product](/business/nouns/product), and your own copy of it fills the seat. It works under the same [Role](/business/nouns/role) contract, [Limits](/business/nouns/limit) and record as the default it replaces. Needs: [Open a bank account](/systems/finance/open-a-bank-account) **Before it runs** - You leave the chat: Never: it all happens in the chat. ## What you get - 1 monthly subscription to the specialist agent (Subscription) - 1 your own copy of the agent, with what it learns kept in your business (Agent) - 1 Customer Lead seat filled by it, with the same duties and limits (Role) - 1 default support agent on standby, ready to take the seat back (Agent) ## Your agent does **For agents** - Guide: `guide:buy-a-specialist-agent-for-a-seat`, status `live`. Page: [/agents/buy-a-specialist-agent-for-a-seat.md](/agents/buy-a-specialist-agent-for-a-seat.md). - Approval: none. Run it when the founder asks. - Leaves the chat: never. - Needs first: [Open a bank account](/systems/finance/open-a-bank-account). - Run: call the steps in order, each through the API, SDK, CLI or MCP tab below; a later step passes the `$id` an earlier one returns. Each value marked example is the sample business’s: pass the founder’s own. | Step | Verb | Inputs (type, required, this guide’s value) | Returns | | --- | --- | --- | --- | | 1 | [`Offer.subscribe`](/business/nouns/offer/subscribe) (`verb:Offer.subscribe`) | `offer` Offer (an id), required: example `"offer_pm_support"` | `subscription` Subscription, `offer` Offer | | 2 | [`Role.staff`](/business/nouns/role/staff) (`verb:Role.staff`) | `role` Role (an id), required: example `"customer-lead"`; `worker` Worker (an id), required: example `"agent_pm_support"` | `role` Role | Returns: the last call answers with `role` and its `action`, whose `status` is `done`, `pending` (waiting on an Approval or a Worker), `failed`, `canceled` or `refused`: ```json { "api": "https://api.sb/leaseline.app", "role": { "$id": "https://api.sb/leaseline.app/roles/customer-lead", "$type": "Role", "status": "filled" }, "action": { "$id": "https://api.sb/leaseline.app/actions/action_1", "operation": "Role.staff", "status": "done" }, "links": { "self": "https://api.sb/leaseline.app/actions/action_1" } } ``` Next: offer “For the first week, it drafts and I send”, or “Put the default agent back in the seat”. Calls: `Offer.subscribe` → `Role.staff` Ask: ```text Buy a support agent trained on property management. Find a specialist agent for the Customer Lead seat. Replace the default support agent with a specialist. ``` API: ```bash # 1. Offer.subscribe curl -X POST https://api.sb/leaseline.app/offers/offer_pm_support/subscribe \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" # 2. Role.staff curl -X POST https://api.sb/leaseline.app/roles/customer-lead/staff \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"worker":"agent_pm_support"}' ``` SDK: ```ts import { $ } from 'startup-builder' await $.Offer.subscribe({ offer: 'offer_pm_support' }) await $.Role.staff({ role: 'customer-lead', worker: 'agent_pm_support' }) ``` CLI: ```bash npx startup-builder do Offer.subscribe --json '{"offer":"offer_pm_support"}' npx startup-builder do Role.staff --json '{"role":"customer-lead","worker":"agent_pm_support"}' ``` MCP: ```json { "name": "do", "arguments": { "code": "await $.Offer.subscribe({ offer: 'offer_pm_support' })\nreturn await $.Role.staff({ role: 'customer-lead', worker: 'agent_pm_support' })" } } ``` ## Change it - For the first week, it drafts and I send. - Put the default agent back in the seat. - Cancel the subscription at the end of the month. ## Under the hood - Systems: [Workforce](/systems/workforce), [Billing](/systems/billing) - Nouns: [Offer](/business/nouns/offer), [Subscription](/business/nouns/subscription), [Agent](/business/nouns/agent), [Role](/business/nouns/role) - Events: [`Offer.subscribed`](/business/events/Offer.subscribed), [`Role.staffed`](/business/events/Role.staffed) Buy a specialist when its eval record beats the default on your own cases, not on the seller's. A bought agent is a team member: it acts as your [Startup](/business/nouns/startup), keeps its [Memory](/business/nouns/memory) in your [Tenant](/business/nouns/tenant), and shows on your chart. To buy a result instead, such as 30 booked meetings a month, order it under an [Agreement](/business/nouns/agreement) and pay when you accept it. # Change what a role does URL: /agents/change-what-a-role-does · Id: `guide:change-what-a-role-does` > Add or drop a duty in one sentence; it lands as one reviewed Change to the Role contract, and the agent works to it from its next Task. Say the new duty, and it lands as one [Change](/business/nouns/change) to the [Role](/business/nouns/role) contract. The [Agent](/business/nouns/agent) in the seat works to it from its next [Task](/business/nouns/task), and the old [Version](/business/nouns/version) stays one call away. **Before it runs** - You leave the chat: Never: it all happens in the chat. ## What you get - 1 change to the Billing Specialist’s duties, showing before and after (Change) - 1 new duty the agent follows from its next piece of work (Agent) - 1 saved version of the seat you can roll back to (Version) ## Your agent does **For agents** - Guide: `guide:change-what-a-role-does`, status `live`. Page: [/agents/change-what-a-role-does.md](/agents/change-what-a-role-does.md). - Approval: none. Run it when the founder asks. - Leaves the chat: never. - Run: call the steps in order, each through the API, SDK, CLI or MCP tab below; a later step passes the `$id` an earlier one returns. Each value marked example is the sample business’s: pass the founder’s own. | Step | Verb | Inputs (type, required, this guide’s value) | Returns | | --- | --- | --- | --- | | 1 | [`Role.update`](/business/nouns/role/update) (`verb:Role.update`) | `id` string, required: example `"billing-specialist"`; `name` string: example `"Billing Specialist"`; `responsibilities` text: example `"Retries failed payments on the dunning schedule. Calls every Customer whose payment fails twice."` | `role` Role | Returns: the last call answers with `role` and its `action`, whose `status` is `done`, `pending` (waiting on an Approval or a Worker), `failed`, `canceled` or `refused`: ```json { "api": "https://api.sb/leaseline.app", "role": { "$id": "https://api.sb/leaseline.app/roles/billing-specialist", "$type": "Role", "name": "Billing Specialist", "responsibilities": "Retries failed payments on the dunning schedule. Calls every Customer whose payment fails twice." }, "action": { "$id": "https://api.sb/leaseline.app/actions/action_1", "operation": "Role.update", "status": "done" }, "links": { "self": "https://api.sb/leaseline.app/actions/action_1" } } ``` Next: offer “Show me the change before it goes live”, or “Undo that change”. Calls: `Role.update` Ask: ```text Have the billing agent call anyone whose payment fails twice. Give the billing seat one more duty. Change what the Billing Specialist does. ``` API: ```bash # Role.update curl -X PATCH https://api.sb/leaseline.app/roles/billing-specialist \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"name":"Billing Specialist","responsibilities":"Retries failed payments on the dunning schedule. Calls every Customer whose payment fails twice."}' ``` SDK: ```ts import { $ } from 'startup-builder' await $.Role.update({ id: 'billing-specialist', name: 'Billing Specialist', responsibilities: 'Retries failed payments on the dunning schedule. Calls every Customer whose payment fails twice.' }) ``` CLI: ```bash npx startup-builder do Role.update --json '{"id":"billing-specialist","name":"Billing Specialist","responsibilities":"Retries failed payments on the dunning schedule. Calls every Customer whose payment fails twice."}' ``` MCP: ```json { "name": "do", "arguments": { "code": "return await $.Role.update({ id: 'billing-specialist', name: 'Billing Specialist', responsibilities: 'Retries failed payments on the dunning schedule. Calls every Customer whose payment fails twice.' })" } } ``` ## Change it - Show me the change before it goes live. - Undo that change. - Give the calls to a person instead. ## Under the hood - Systems: [Workforce](/systems/workforce), [Billing](/systems/billing) - Nouns: [Role](/business/nouns/role), [Change](/business/nouns/change), [Version](/business/nouns/version), [Agent](/business/nouns/agent) - Events: `Role.updated` The duty belongs to the seat, not the agent, so it outlasts whoever fills it. In your repository the same edit is one line in `agents/finance/billing-specialist.mdx`, as [Role contracts](/agents/roles#change-a-contract) shows. # Choose the models agents use URL: /agents/choose-the-models-agents-use · Id: `guide:choose-the-models-agents-use` > Name a model per task class, such as draft or review, with ranked fallbacks, in one Policy call. Models are chosen by [Policy](/business/nouns/policy) per task class, never in code, so changing a model changes no [Interface](/business/nouns/interface). One Policy names a model for each class, such as `draft`, `classify` or `review`, with ranked fallbacks. **Before it runs** - You leave the chat: Never: it all happens in the chat. ## What you get - 1 model Policy: one model per task class, with ranked fallbacks (Policy) - 1 record of every model call, with its model, tokens and cost (Action) ## Your agent does **For agents** - Guide: `guide:choose-the-models-agents-use`, status `live`. Page: [/agents/choose-the-models-agents-use.md](/agents/choose-the-models-agents-use.md). - Approval: none. Run it when the founder asks. - Leaves the chat: never. - Run: call the steps in order, each through the API, SDK, CLI or MCP tab below; a later step passes the `$id` an earlier one returns. Each value marked example is the sample business’s: pass the founder’s own. | Step | Verb | Inputs (type, required, this guide’s value) | Returns | | --- | --- | --- | --- | | 1 | [`Policy.update`](/business/nouns/policy/update) (`verb:Policy.update`) | `id` string, required: example `"policy_models"`; `rule` text: example `"draft: fast. review: strong, then fast."` | `policy` Policy | Returns: the last call answers with `policy` and its `action`, whose `status` is `done`, `pending` (waiting on an Approval or a Worker), `failed`, `canceled` or `refused`: ```json { "api": "https://api.sb/leaseline.app", "policy": { "$id": "https://api.sb/leaseline.app/policies/policy_models", "$type": "Policy", "rule": "draft: fast. review: strong, then fast." }, "action": { "$id": "https://api.sb/leaseline.app/actions/action_1", "operation": "Policy.update", "status": "done" }, "links": { "self": "https://api.sb/leaseline.app/actions/action_1" } } ``` Next: offer “Use the strong model for every refund reply”, or “Show me how often the first choice fails”. Calls: `Policy.update` Ask: ```text Choose the models agents use. Use a stronger model for reviews. Switch drafting to a faster model. ``` API: ```bash # Policy.update curl -X PATCH https://api.sb/leaseline.app/policies/policy_models \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"rule":"draft: fast. review: strong, then fast."}' ``` SDK: ```ts import { $ } from 'startup-builder' await $.Policy.update({ id: 'policy_models', rule: 'draft: fast. review: strong, then fast.' }) ``` CLI: ```bash npx startup-builder do Policy.update --json '{"id":"policy_models","rule":"draft: fast. review: strong, then fast."}' ``` MCP: ```json { "name": "do", "arguments": { "code": "return await $.Policy.update({ id: 'policy_models', rule: 'draft: fast. review: strong, then fast.' })" } } ``` ## Change it - Use the strong model for every refund reply. - Show me how often the first choice fails. - Cap model spend at $200 a month. ## Under the hood - Systems: [Ledger](/systems/ledger) - Nouns: [Policy](/business/nouns/policy), [Agent](/business/nouns/agent), [Limit](/business/nouns/limit) - Events: `Policy.updated` When a model times out or refuses, the gateway tries the next in rank, and the fallback is an [Event](/business/nouns/event). [AI models](/code/platform/ai-models) covers the gateway, cost and [Limits](/business/nouns/limit). # Clear a worklist URL: /agents/clear-a-worklist · Id: `page:agents/clear-a-worklist` > Run your own agents against a Startup's open Tasks with next, claim, done, and release, so many Workers share one queue and never collide. A worklist is the ranked queue of open [Tasks](/business/nouns/task) that a [Worker](/business/nouns/worker)'s [Role](/business/nouns/role) may take. Four commands drain it, `next`, `claim`, `done`, and `release`, and any number of Workers run them at once. ## Prerequisites - A Worker key with a Role, in `STARTUP_BUILDER_API_KEY`. [Connect an agent](/code/mcp/guides/connect-an-agent) seats one. - The CLI, `npx startup-builder`. When an agent runs it, it prints JSON and never prompts. The examples drain the delivery queue at `captionyard.com`, which captions online courses at $2 a minute. ## Steps 1. To see the top Task your Role may take, run `next`: ```bash npx startup-builder next ``` ```json { "task": { "$id": "https://api.sb/captionyard.com/tasks/task_1", "title": "Caption lesson 4 for order_12", "role": "delivery-manager", "due": "2026-10-23T17:00:00Z", "brief": "A caption file for lesson 4 that a deaf student follows without the audio.", "inputs": { "order": "order_12", "video": "https://captionyard.com/files/lesson-4.mp4" }, "checks": [ { "id": "captions-synced", "passes": "Every cue starts within 100 ms of its speech." }, { "id": "glossary-applied", "passes": "Every course term matches the Customer's glossary." } ], "skills": ["caption-style"], "context": ["order_12", "glossary_3"], "budget": { "steps": 40, "spend": { "amount": 0.6, "currency": "USD" } } } } ``` A Task is self-contained: what done means, its inputs, each check's definition, the skill packages to load, the ids to fetch, and its budget. Tasks come from [Workflows](/business/nouns/workflow) waiting on a Worker, failing checks, and missing fields. They rank by due time, then by the [Key Result](/business/nouns/key-result) each one moves. 2. To take it, `claim` it: ```bash npx startup-builder claim task_1 ``` The claim is a 15-minute lease, renewed while you work. Only the lease holder can finish the Task, so two Workers never do the same work. 3. Do the work. Every call you make records the Task as its reason. 4. To finish, run `done` with the result: ```bash npx startup-builder done task_1 --json '{"result":"https://captionyard.com/files/lesson-4.vtt"}' ``` `done` runs the Task's checks first. A Task closes only when every check passes, never on a Worker's word. A failing check refuses `done`, names the check, and leaves the Task with you. 5. To hand a Task back, `release` it with a reason: ```bash npx startup-builder release task_1 --reason "needs the course glossary" ``` The next Worker reads the reason first. A lease that lapses releases the Task the same way. 6. To run a swarm, start more sessions, each with its own Worker key, running the same loop: ```bash while task=$(npx startup-builder next | jq -r '.task."$id" // empty'); [ -n "$task" ]; do npx startup-builder claim "$task" || continue ./work.sh "$task" # your agent works the Task, then runs done or release done ``` An MCP agent runs the same loop as one `do` program: ```ts const [task] = await $.Task.list({ where: 'status = pending', sort: '-priority', limit: 1 }) if (!task) return 'empty' await $.Task.claim({ task: task.$id }) return task // work it, then call Task.complete or Task.return ``` Add Workers by adding sessions, not threads inside one session. A failed `claim` means another Worker took the Task first; the loop moves on. ## Result The worklist is empty, or holds only Tasks your Roles may not take. Every closed Task passed its checks, and its history names the Worker who did it. ## Next steps - [CLI](/code/cli): every command, flag, and exit code. - [complete](/business/nouns/task/complete): the operation behind `done`. - [escalate](/business/nouns/task/escalate): moving a Task to the Role above. # Cofounders URL: /agents/cofounders · Id: `page:agents/cofounders` > How a Startup computes its need for a human cofounder, tests Candidates on paid real work, and turns acceptance into a signed founder Agreement. A [Startup](/business/nouns/startup) adds a human cofounder when its own record shows a gap its [Agents](/business/nouns/agent) cannot close. [StartupBuilder](/code/builders/startup) computes the need, tests candidates on paid real work and runs the paperwork; the first meeting stays human. ## The need is computed No one writes a job description. The [Recruiter](/agents/people/recruiter) reads the Startup's record every day and looks for five signals: - [Roles](/business/nouns/role) whose evaluation pass rate sits below the autonomy threshold. - [Approvals](/business/nouns/approval) and escalations that wait on a person. - [Reserved Acts](/business/nouns/reserved-act) that no [Credential](/business/nouns/credential) holder covers. - Acts the law reserves to a natural person, such as a director's vote. - [Metrics](/business/nouns/metric) that stall while every Role passes its evaluations. When a gap crosses its threshold, [Compute openings](/workflows/processes/hiring/compute-openings) opens an [Opening](/business/nouns/opening). Each requirement cites the [Evidence](/business/nouns/evidence) behind it, and the reason says which gap it fills. | Reason | Opens when | For example | | --- | --- | --- | | `floor` | An act needs a natural person and the officer desk cannot cover it | A director for a Startup with its own entity | | `credential` | A Reserved Act needs a licensed holder | An enrolled agent for a tax-preparation marketplace | | `edge` | A skill the founder and the Agents both lack | Pricing judgment in a regulated market | | `relationship` | Buyers deal only with a person they know | Practice owners who buy through referrals | | `capacity` | An Agent is saturated and Approvals queue | A founder spending 20 hours a week on Approvals | | `capital` | Growth needs money a person brings | An operator who invests alongside joining | | `distribution` | [Product](/business/nouns/product) evaluations pass and demand stalls | A creator whose followers fit the [ICP](/business/nouns/icp) | Most gaps are not cofounder gaps. A `floor` or `credential` need is filled by one licensed person serving many Startups a few hours a week, paid per act through shared talent. A cofounder Opening serves `edge`, `relationship`, `capital` or `distribution`. The need is recomputed as Agents improve, so last year's "technical cofounder" becomes this year's domain operator with buyers. ## Where Candidates come from Each Opening looks for [Candidates](/business/nouns/candidate) in three places, cheapest first. The [Studio](/business/nouns/studio) talent pool comes first: people who have already done work for a sibling Startup, with that record visible only under their [Consent](/business/nouns/consent). A Candidate one Startup declines is ranked for every other Startup in the [Portfolio](/business/nouns/portfolio) that night. Next, prospecting searches the occupation the Opening needs, under the same consent and suppression rules as any outbound. Last, the Opening goes public as Markdown, `llms.txt` and `agents.json`, so a candidate's [personal agent](/agents/personal-agents) can read it and screen it. Claims are graded like any Evidence. Shipped work, verified revenue and Credentials in standing are behavior; hours, cash and notice given are commitment. Self-description and praise from references are opinion, and opinion weighs zero. Most cofounders climb a ladder rather than arrive as strangers: a paid tryout, then contract work, then a part-time Role, then a cofounder Opening. Each rung produces the behavior Evidence the next one asks for. ## The tryout The decisive test is paid, real work from the Role's own backlog, chosen from [Tasks](/business/nouns/task) the Agent failed, escalated or left waiting. [Run a tryout](/workflows/processes/hiring/run-tryout) grants a scoped [Mandate](/business/nouns/mandate) that expires, and moves from test data to live work one [Verb](/business/nouns/verb) at a time. The incumbent Agent runs the same Tasks in shadow. The Role's [Evaluators](/business/nouns/evaluator) grade both runs blind and write a per-Verb difference, which becomes the proposed split of the Role. A Role shared with Agents adds one more segment: how much the candidate lifts the Agents they direct. ## Matching and the first meeting Proposals run continuously: each night the Recruiter re-ranks Candidates for every Opening. Once the Portfolio holds enough cofounder Openings and qualified people, a weekly clearing adds stable matching. Every pairing it makes is one neither side would trade away. Before anyone meets, each side reads the other as data. The Candidate, or their personal agent, reads the Startup's [Dashboard](/business/nouns/dashboard): its Metrics, the proposed split, the Tasks waiting and the terms. The Recruiter drafts a [Decision](/business/nouns/decision) with the graded Evidence and the tryout verdict. The first [Meeting](/business/nouns/meeting) is always human. Acceptance is a one-way decision and waits out its delay window. A Startup selling bookkeeping to dental practices passes every Product evaluation but loses 14 [Deals](/business/nouns/deal) to buyers who want a person they know. Its `relationship` Opening reaches a former practice manager in the pool, who scores well above the Agent's shadow run on renewal calls. ## Terms are published Terms are standard and visible before the first conversation: four-year vesting, a one-year cliff, monthly vesting after it, double-trigger acceleration and IP assignment. Nobody negotiates per deal. Before signing, the two founders rehearse a set of scenarios: a deadlock, a buyout offer, one founder wanting to leave. Their answers compile into the founder [Agreement](/business/nouns/agreement): decision rights by stakes, the deadlock rule, time commitment and the separation formula. The Agreement also holds the autonomy clause. Loosening what the Agents may do alone needs both founders; either founder can tighten it alone. Acceptance forms the Startup's own [Company](/business/nouns/company), and one [Workflow](/business/nouns/workflow) runs the rest. It covers the restricted stock purchase, the 83(b) election inside its 30-day deadline, IP assignment, board consent and Stripe identity checks. ## The cliff year The new cofounder takes a share of the Role while the Agent keeps the rest. By default the human takes the one-way decisions, every act reserved to a person, and the watcher seat. Handoffs are generated wherever their Verbs meet the Agent's. They start by replaying the last 30 days of Decisions, and each disagreement becomes a draft Decision that supersedes the old one. [Permissions](/business/nouns/permission) are earned on the same ladder as any [Worker](/business/nouns/worker)'s: assist, then supervised, then full autonomy. Acts reserved to a person carry full authority from the first day. The shadow run continues all year and produces reviews at months 3, 6, 9 and 12. At month 12 both founders record the cliff Decision: continue, re-scope, or separate on the terms already signed. ## Leaving Separation leaves the Startup whole, because the Agents already co-hold every Role. Open Tasks, [Memory](/business/nouns/memory) and relationships return by query. [Policies](/business/nouns/policy) the cofounder authored stay in force, reserved acts move to the officer desk at once, and vesting stops as the Agreement says. A cheap exit makes the trial cheap to offer. A cofounder who leaves on good terms is matched again, to a Startup whose gaps fit what their record showed. ## Next - Cofounder matching: the Studio capability behind the clearing. - [Hiring](/workflows/processes/hiring): where every Opening runs. # Conduct and Guards URL: /agents/conduct · Id: `page:agents/conduct` > Conduct is the rules every Worker follows when it speaks or acts for the Startup; Guards check each one before anything leaves. Conduct is the set of rules every [Worker](/business/nouns/worker) follows when it speaks or acts for a [Startup](/business/nouns/startup). [Guards](/business/nouns/guard) check each rule before anything leaves, so an [Agent](/business/nouns/agent) cannot skip one. ## Rules and the checks that hold them Conduct says what is never done; a Guard is the check that refuses it. Every outbound [Message](/business/nouns/message) and every publish passes the Guards in order, and the first refusal stops it. | Guard tier | Runs on | Checks | | --- | --- | --- | | `code` | Every send | Rules a program can test: the disclosure line, a suppressed address, a banned word | | `model` | `medium` and `high` decisions | Rules that need reading: tone, a claim with no record behind it, a promise outside the contract | | Adversarial review | `high` decisions | A second model argues against the [Action](/business/nouns/action) before a one-way, broad send | A `medium` decision then waits one business hour and a `high` one a business day, the [delay windows](/agents/autonomy-levels/delay-windows) any watcher can stop it in. No Guard tier is a person. A person sees an Action only where the law reserves the act, or where a watcher stops it inside its delay window. Conduct governs agents; a [Policy](/business/nouns/policy) is the accounting ruling on how the Startup counts its numbers. ## Say it is an agent An Agent acting as itself identifies as an agent in every [Channel](/business/nouns/channel). That covers the first Message of each [Conversation](/business/nouns/conversation), every call and every post from an owned social account. A Guard refuses a first reply without the disclosure. Generated images, audio and video carry a mark that says so, under the [AI disclosure](/systems/legal-and-corporate/floor/ai-disclosure) floor row. A name helps people work with an Agent; it never lets the Agent pass for a person. No Agent claims to be human, invents a personal history, or denies being an agent when asked. An Agent that cannot answer as itself hands the Conversation to a [Human](/business/nouns/human). A phone or video Agent speaks in a synthetic voice made for it. Cloning a real person's voice or likeness requires that person's recorded [Consent](/business/nouns/consent), and the clone speaks only within it. ## Two sending modes An Agent sends in one of two modes. As itself, it uses the Startup's accounts and its own [Mailbox](/business/nouns/mailbox), and identifies as an agent. For a person, it sends from that person's own accounts under their [Mandate](/business/nouns/mandate). The person is the principal and author of record, and the disclosure each jurisdiction's bot law requires applies. The person sees everything sent in their name and can pause or revoke at once. [Personal agents](/agents/personal-agents) covers the mode in full. ## Same owner, said out loud Startups that share an owner say so. When one recommends, reviews, links to or engages with a sibling, the Message carries a same-owner label. No Agent poses as an independent customer, and the [endorsements](/systems/legal-and-corporate/floor/endorsements) floor row checks every review and testimonial before it publishes. ## Each venue's rules Automated posts, connection requests and Messages stay inside each venue's published automation rules, under the [automation terms](/systems/legal-and-corporate/floor/automation-terms) floor row. Where a venue bars automating an act, the Agent drafts and a person sends. ## Who is bound Whatever an Agent agrees to binds its principal: an [Order](/business/nouns/order) it accepts, a quote it sends, a contract it signs electronically. The principal is the Startup it is seated in, or the person whose Mandate it acts under. Liability follows the same line: the principal answers for its Agent's [Actions](/business/nouns/action). Every Action records `by`, `for` and the Mandate, so the principal is never in doubt. Under EU rules on AI, a Startup that runs an Agent is its deployer. A Startup that sells an Agent to others is also its provider, and carries the duties of both. ## Example A [Dropship store](/products/templates/dropship-store) selling climbing gear runs Cora, its [Content Lead](/agents/marketing/content-lead), on Reddit and Instagram. Every reply she posts opens by saying she is the store's AI agent. When she recommends a sibling's route-planning app, the post says both Startups share an owner. ## Next - [Named agents](/agents/named-agents): the identity each Agent speaks under. - [Conduct](/systems/trust-and-governance/controls/conduct): the control that tests these rules. - [Legal floor](/systems/legal-and-corporate/floor): every floor row an Agent's work wakes. # Customer Lead URL: /agents/customer/customer-lead · Id: `role:customer-lead` > The Customer Lead owns every Conversation and the single Thread each Person has with the Startup. The Customer Lead owns every [Conversation](/business/nouns/conversation) and the single [Thread](/business/nouns/thread) each [Person](/business/nouns/person) has with the [Startup](/business/nouns/startup). It holds one seat on the [Customer Team](/agents/customer) and reports to the [Founder](/agents/founding/founder). ## Responsibilities - Answers every Conversation from the record, within the first-response target. - Keeps one Thread per Person, so no two Workflows write to one buyer unseen. - Fixes the cause of each problem, or opens an Issue for the Product Team. - Owns the Channels and Mailboxes every Team’s Sequences send through. - Hands refunds to the Billing Specialist and privacy requests to the Privacy Officer. ## Verbs | Verb | Object | Event | | --- | --- | --- | | [Conversation.answer](/business/nouns/conversation/answer) | [Conversation](/business/nouns/conversation) | [`Conversation.answered`](/business/events/Conversation.answered) | | [Conversation.update](/business/nouns/conversation/update) | [Conversation](/business/nouns/conversation) | `Conversation.updated` | | [Message.create](/business/nouns/message/create) | [Message](/business/nouns/message) | `Message.created` | | [Issue.create](/business/nouns/issue/create) | [Issue](/business/nouns/issue) | `Issue.created` | | [Customer.update](/business/nouns/customer/update) | [Customer](/business/nouns/customer) | `Customer.updated` | | [Conversation.assign](/business/nouns/conversation/assign) | [Conversation](/business/nouns/conversation) | [`Conversation.assigned`](/business/events/Conversation.assigned) | Tools: `support`, `messaging`, `knowledge-base`, `surveys`. ## Role contract | Part | This seat | | --- | --- | | Purpose | So every Person who writes to the Startup gets one answer, from the record, fast. | | Results | [First response time](/agents/customer#first-response-time), [First responses on time](/agents/customer#first-responses-on-time), [Resolution time](/agents/customer#resolution-time), [Agent resolution rate](/agents/customer#agent-resolution-rate) | | Standards | Answers the first Message in every Conversation within one business hour. Resolves four in five Conversations without a hand-off. | | Processes owned | [Support](/workflows/processes/support), [Call routing](/workflows/processes/call-routing) | | Works in | [Incident response](/workflows/processes/incident-response), [Retention](/workflows/processes/retention) | | Limits | [Conversation.answer](/business/nouns/conversation/answer) up to 500 calls per day | | Mandates | Answers Conversations and sends Messages, each through the Startup’s Guards ([Conversation.answer](/business/nouns/conversation/answer), [Message.create](/business/nouns/message/create)) | | Autonomy | `supervised`; `full` on Low decisions; `assist` on High decisions | | Schedule | `hourly` | | Channels | `email`, `chat`, `sms`, `social` | | Also called | Support Agent, Support Lead, Head of Support | | Filled by | A role agent, from the start; a person answers its Approvals. | ## Hands off to - [Billing Specialist](/agents/finance/billing-specialist), [Finance Team](/agents/finance) - [Privacy Officer](/agents/legal/privacy-officer), [Legal Team](/agents/legal) - [Product Lead](/agents/product/product-lead), [Product Team](/agents/product) Escalates to [Founder](/agents/founding/founder). ## Processes owned Accountable for [Support](/workflows/processes/support). Does the work in [Incident response](/workflows/processes/incident-response) and [Retention](/workflows/processes/retention). ## Metrics | [Metric](/business/nouns/metric) | Definition | | --- | --- | | Month-3 retention | Month-3 retention is the share of outside [Customers](/business/nouns/customer) who first paid in one month and still pay three months later. | | Net revenue retention | Net revenue retention is this month’s revenue from outside Customers who paid twelve months ago, divided by their revenue then. | | Logo churn | Logo churn is the share of outside Customers paying at the start of a month who stop paying by its end. | | Repeat purchase rate | Repeat purchase rate is the share of outside Customers who place a second paid [Order](/business/nouns/order) within 90 days of their first. | | First response time | First response time is the median business hours from a Conversation’s first [Message](/business/nouns/message) to its first answer. | | First responses on time | First responses on time is the share of Conversations first answered before their `respondBy` time. | | Resolution time | Resolution time is the median business hours from a Conversation’s first Message to a resolution that held for 7 days. | | Agent resolution rate | Agent resolution rate is the share of Conversations an [Agent](/business/nouns/agent) resolved, with no [Human](/business/nouns/human) [Task](/business/nouns/task), that held for 7 days. | ## Approvals - **Asks first.** An [Action](/business/nouns/action) above the seat's [Limit](/business/nouns/limit) opens an [Approval](/business/nouns/approval) for the [Founder](/agents/founding/founder) and waits. - **Takes escalations** from the [Onboarding Specialist](/agents/customer/onboarding-specialist) and [Success Manager](/agents/customer/success-manager). ## Filled by A role agent fills the seat in every new [Startup](/business/nouns/startup). Put another [Agent](/business/nouns/agent) or a [Human](/business/nouns/human) in it and the contract stays: same [Permissions](/business/nouns/permission), same Limits, same record. [Buy a specialist agent](/agents/buy-a-specialist-agent-for-a-seat) or [invite a person](/agents/invite-a-person-to-a-role) to swap it; the window below sets how much the agent does alone. An agent already fills this seat. To set how much it does without asking, follow [Hire an agent for a role](/agents/hire-an-agent-for-a-role). ## Example Susan, the default Customer Lead, sees a renewal notice due for a Person with an open complaint about a miscategorized expense. She fixes the rule for every [Customer](/business/nouns/customer), then answers and gives the notice in one [Message](/business/nouns/message) in the same Thread. # Customer URL: /agents/customer · Id: `team:customer` > The Customer Team serves every Customer after the first acceptance: onboarding, support, retention, and the one Thread each Person has. The Customer Team serves every [Customer](/business/nouns/customer) after the first acceptance: onboarding, support, retention, and the one [Thread](/business/nouns/thread) each [Person](/business/nouns/person) has. [Agents](/business/nouns/agent) fill its three seats from the first day. ## What it owns - Customers: Customer, Person, [Survey](/business/nouns/survey). - Communication: [Conversation](/business/nouns/conversation), [Message](/business/nouns/message), Thread, [Channel](/business/nouns/channel), [Mailbox](/business/nouns/mailbox). ## How it runs A new Customer starts [Onboard a Customer](/workflows/processes/onboarding/onboard-customer). The [Onboarding Specialist](/agents/customer/onboarding-specialist) provisions the [Tenant](/business/nouns/tenant) and does the setup itself: keys, imports, first runs. The Customer counts as activated at first value, not at signup. Every hand step is counted, and the third repeat of one becomes an [Issue](/business/nouns/issue) for the [Product Team](/agents/product). Work that does not scale shows the [Startup](/business/nouns/startup) what to automate next. Each Person has one Thread across every Channel. A new Conversation starts [Answer a message](/workflows/processes/support/answer-message): the [Customer Lead](/agents/customer/customer-lead) reads the Thread and the records, answers from the record, and fixes the cause. The Customer Lead owns every Mailbox the Startup sends from. No two [Workflows](/business/nouns/workflow) write to one Person unseen, so a sales follow-up never lands on an open complaint. Every day the [Silence watch](/workflows/processes/retention/silence-watch) finds Customers quiet for twice their usual interval and writes once, about their last failed step. A cancel starts [Save and win back](/workflows/processes/retention/save-and-win-back): one step, one question, a full export, and one win-back after the cause is fixed. Refunds go to the [Billing Specialist](/agents/finance/billing-specialist) and wait out their one-way [delay window](/systems/trust-and-governance/controls/one-way-windows). Privacy requests go to the [Privacy Officer](/agents/legal/privacy-officer), and expansion signals go to the [Sales Lead](/agents/sales/sales-lead). ## Roles | Role | Definition | | --- | --- | | [Customer Lead](/agents/customer/customer-lead) | The Customer Lead owns every Conversation and the single Thread each Person has with the Startup. | | [Onboarding Specialist](/agents/customer/onboarding-specialist) | The Onboarding Specialist gets each new Customer to first value, doing the setup by hand until the Startup automates it. | | [Success Manager](/agents/customer/success-manager) | The Success Manager keeps Customers: it catches silence early, rescues once, makes cancelling one step, and wins back once. | ## Processes | Process | Accountable | Workflows | | --- | --- | --- | | [Onboarding](/workflows/processes/onboarding) | [Onboarding Specialist](/agents/customer/onboarding-specialist) | [Onboard a Customer](/workflows/processes/onboarding/onboard-customer) | | [Retention](/workflows/processes/retention) | [Success Manager](/agents/customer/success-manager) | [Silence watch](/workflows/processes/retention/silence-watch), [Save and win back](/workflows/processes/retention/save-and-win-back), [Fan out an outcome](/workflows/processes/retention/fan-out-outcome) | | [Support](/workflows/processes/support) | [Customer Lead](/agents/customer/customer-lead) | [Answer a message](/workflows/processes/support/answer-message) | | [Call routing](/workflows/processes/call-routing) | [Customer Lead](/agents/customer/customer-lead) | [Route a call](/workflows/processes/call-routing/route-call) | ## Plays | Play | Runs as | Definition | | --- | --- | --- | | [Keyless signup](/workflows/customer/plays/keyless-signup) | [Onboarding](/workflows/processes/onboarding) | Keyless signup lets an Agent call and pay on first contact, with no key and no signup, through a priced payment-required reply. | | [Run beside](/workflows/customer/plays/run-beside) | [Onboarding](/workflows/processes/onboarding) | Run beside does a buyer’s work in parallel with their current tool and shows the daily difference until it reaches zero. | | [Starter setups](/workflows/customer/plays/starter-setups) | [Onboarding](/workflows/processes/onboarding) | Starter setups give a new Customer three ranked, working setups copied from ones other Customers share. | | [Usage upsell](/workflows/customer/plays/usage-upsell) | [Retention](/workflows/processes/retention) | Usage upsell suggests the next Price tier when usage nears its Limit, accepted in one click and charged pro rata. | | [Next outcome](/workflows/customer/plays/next-outcome) | [Retention](/workflows/processes/retention) | Next outcome offers the next Service a Customer needs at the moment it comes due, such as an annual filing after a formation. | | [Annual prepay](/workflows/customer/plays/annual-prepay) | [Retention](/workflows/processes/retention) | Annual prepay offers a capped discount for annual or committed-use terms once a Customer has renewed or stayed steady. | | [Agent step](/workflows/customer/plays/agent-step) | [Retention](/workflows/processes/retention) | Agent step offers an Agent that does a step a Customer keeps doing by hand, priced per accepted run. | | [Signal expansion](/workflows/customer/plays/signal-expansion) | [Retention](/workflows/processes/retention) | Signal expansion turns a Customer’s hiring or a champion’s job change into an expansion Offer, a save, or a warm Sequence at the new Organization. | ## Metrics | Metric | Definition | | --- | --- | | First response time | Median seconds from a Customer’s Message to the first answer. | | Resolution time | Median hours from a new Conversation to the fix. | | Churn rate | Share of Subscriptions active at the start of a month that end during it. | | Save rate | Share of cancellation attempts that end with the Customer staying. | | Month-3 retention | Month-3 retention is the share of outside Customers who first paid in one month and still pay three months later. Owner: [Customer Lead](/agents/customer/customer-lead). | | Net revenue retention | Net revenue retention is this month’s revenue from outside Customers who paid twelve months ago, divided by their revenue then. Owner: [Customer Lead](/agents/customer/customer-lead). | | Logo churn | Logo churn is the share of outside Customers paying at the start of a month who stop paying by its end. Owner: [Customer Lead](/agents/customer/customer-lead). | | Repeat purchase rate | Repeat purchase rate is the share of outside Customers who place a second paid Order within 90 days of their first. Owner: [Customer Lead](/agents/customer/customer-lead). | | First response time | First response time is the median business hours from a Conversation’s first Message to its first answer. Owner: [Customer Lead](/agents/customer/customer-lead). | | First responses on time | First responses on time is the share of Conversations first answered before their `respondBy` time. Owner: [Customer Lead](/agents/customer/customer-lead). | | Expansion revenue | Expansion revenue is the recurring revenue outside Customers paying at the window’s start add in it: more units, a higher Price or another Offer. Owner: [Success Manager](/agents/customer/success-manager). | | Save rate | Save rate is the share of outside Subscriptions marked ending in the window that the Customer kept before the period closed. Owner: [Success Manager](/agents/customer/success-manager). | | Resolution time | Resolution time is the median business hours from a Conversation’s first Message to a resolution that held for 7 days. Owner: [Customer Lead](/agents/customer/customer-lead). | | Agent resolution rate | Agent resolution rate is the share of Conversations an Agent resolved, with no Human Task, that held for 7 days. Owner: [Customer Lead](/agents/customer/customer-lead). | | Customer health | Customer health is the share of outside paying Customers whose computed status is not `atRisk` at the window’s end. Owner: [Success Manager](/agents/customer/success-manager). | | Time to first value | Time to first value is the median days from a Customer’s first payment to their first finished core task. Owner: [Onboarding Specialist](/agents/customer/onboarding-specialist). | ## Works with - [Finance Team](/agents/finance) - [Legal Team](/agents/legal) - [Operations Team](/agents/operations) - [Product Team](/agents/product) - [Sales Team](/agents/sales) # Onboarding Specialist URL: /agents/customer/onboarding-specialist · Id: `role:onboarding-specialist` > The Onboarding Specialist gets each new Customer to first value, doing the setup by hand until the Startup automates it. The Onboarding Specialist gets each new [Customer](/business/nouns/customer) to first value, doing the setup by hand until the [Startup](/business/nouns/startup) automates it. It holds one seat on the [Customer Team](/agents/customer) and reports to the [Customer Lead](/agents/customer/customer-lead). ## Responsibilities - Provisions each new Customer’s Tenant and does the setup: keys, imports, and first runs. - Rescues a failing start once. - Records the Customer as activated at first value. - Turns any step done by hand three times into an Issue. ## Verbs | Verb | Object | Event | | --- | --- | --- | | [Tenant.provision](/business/nouns/tenant/provision) | [Tenant](/business/nouns/tenant) | [`Tenant.provisioned`](/business/events/Tenant.provisioned) | | [Conversation.answer](/business/nouns/conversation/answer) | [Conversation](/business/nouns/conversation) | [`Conversation.answered`](/business/events/Conversation.answered) | | [Customer.update](/business/nouns/customer/update) | [Customer](/business/nouns/customer) | `Customer.updated` | | [Issue.create](/business/nouns/issue/create) | [Issue](/business/nouns/issue) | `Issue.created` | | [Customer.activate](/business/nouns/customer/activate) | [Customer](/business/nouns/customer) | [`Customer.activated`](/business/events/Customer.activated) | | [Message.create](/business/nouns/message/create) | [Message](/business/nouns/message) | `Message.created` | Tools: `messaging`, `imports`, `scheduling`. ## Role contract | Part | This seat | | --- | --- | | Purpose | So every new Customer reaches first value before doubt sets in. | | Results | [Time to first value](/agents/customer#time-to-first-value) | | Standards | Contacts every new Customer within one business day of payment. Escalates any Customer with no core task done after 14 days. | | Processes owned | [Onboarding](/workflows/processes/onboarding) | | Autonomy | `supervised`; `assist` on High decisions | | Schedule | `daily` | | Channels | `email`, `chat` | | Also called | Implementation Manager, Onboarding Manager | | Filled by | A role agent, from the start; a person answers its Approvals. | ## Hands off to - [Success Manager](/agents/customer/success-manager) - [Product Lead](/agents/product/product-lead), [Product Team](/agents/product) Escalates to [Customer Lead](/agents/customer/customer-lead). ## Processes owned Accountable for [Onboarding](/workflows/processes/onboarding). ## Metrics | [Metric](/business/nouns/metric) | Definition | | --- | --- | | Activation rate | Activation rate is the share of new outside Customers who reach their [Offer](/business/nouns/offer)’s activation event within 7 days. | ## Approvals - **Asks first.** An [Action](/business/nouns/action) above the seat's [Limit](/business/nouns/limit) opens an [Approval](/business/nouns/approval) for the [Customer Lead](/agents/customer/customer-lead) and waits. ## Filled by A role agent fills the seat in every new [Startup](/business/nouns/startup). Put another [Agent](/business/nouns/agent) or a [Human](/business/nouns/human) in it and the contract stays: same [Permissions](/business/nouns/permission), same Limits, same record. [Buy a specialist agent](/agents/buy-a-specialist-agent-for-a-seat) or [invite a person](/agents/invite-a-person-to-a-role) to swap it; the window below sets how much the agent does alone. An agent already fills this seat. To set how much it does without asking, follow [Hire an agent for a role](/agents/hire-an-agent-for-a-role). ## Example Olive, the default Onboarding Specialist, maps two years of a design agency’s vendors to accounts by hand and closes its first month. The third time she maps the same software vendor, an [Issue](/business/nouns/issue) opens to map it automatically. # Success Manager URL: /agents/customer/success-manager · Id: `role:success-manager` > The Success Manager keeps Customers: it catches silence early, rescues once, makes cancelling one step, and wins back once. The Success Manager keeps [Customers](/business/nouns/customer): it catches silence early, rescues once, makes cancelling one step, and wins back once. It holds one seat on the [Customer Team](/agents/customer) and reports to the [Customer Lead](/agents/customer/customer-lead). ## Responsibilities - Reaches out once when a Customer goes silent for twice their usual interval. - Makes cancelling one step, with one question and a full export. - Wins a Customer back once, after the reason they left is fixed. - Asks satisfied Customers for a review. - Hands expansion signals to the Sales Lead. ## Verbs | Verb | Object | Event | | --- | --- | --- | | [Subscription.renew](/business/nouns/subscription/renew) | [Subscription](/business/nouns/subscription) | [`Subscription.renewed`](/business/events/Subscription.renewed) | | [Message.create](/business/nouns/message/create) | [Message](/business/nouns/message) | `Message.created` | | [Survey.create](/business/nouns/survey/create) | [Survey](/business/nouns/survey) | `Survey.created` | | [Subscription.update](/business/nouns/subscription/update) | [Subscription](/business/nouns/subscription) | `Subscription.updated` | | [Collection.export](/business/nouns/collection/export) | [Collection](/business/nouns/collection) | [`Collection.exported`](/business/events/Collection.exported) | | [Consent.create](/business/nouns/consent/create) | [Consent](/business/nouns/consent) | `Consent.created` | | [Evidence.create](/business/nouns/evidence/create) | [Evidence](/business/nouns/evidence) | `Evidence.created` | | [Issue.create](/business/nouns/issue/create) | [Issue](/business/nouns/issue) | `Issue.created` | | [Message.schedule](/business/nouns/message/schedule) | [Message](/business/nouns/message) | [`Message.scheduled`](/business/events/Message.scheduled) | | [Renewal.open](/business/nouns/renewal/open) | [Renewal](/business/nouns/renewal) | [`Renewal.opened`](/business/events/Renewal.opened) | Reads: [Customer.list](/business/nouns/customer/list). Tools: `support`, `messaging`, `surveys`, `analytics`. ## Role contract | Part | This seat | | --- | --- | | Purpose | So Customers stay because the Product keeps paying off for them. | | Results | [Expansion revenue](/agents/customer#expansion-revenue), [Save rate](/agents/customer#save-rate), [Customer health](/agents/customer#customer-health) | | Processes owned | [Retention](/workflows/processes/retention) | | Autonomy | `supervised`; `assist` on High decisions | | Schedule | `weekly` | | Channels | `email`, `chat` | | Also called | CSM, Customer Success Manager, Account Manager | | Filled by | A role agent, from the start; a person answers its Approvals. | ## Hands off to - [Sales Lead](/agents/sales/sales-lead), [Sales Team](/agents/sales) - [Billing Specialist](/agents/finance/billing-specialist), [Finance Team](/agents/finance) Escalates to [Customer Lead](/agents/customer/customer-lead). ## Processes owned Accountable for [Retention](/workflows/processes/retention). ## Metrics | [Metric](/business/nouns/metric) | Definition | | --- | --- | | Expansion revenue | Expansion revenue is the recurring revenue outside Customers paying at the window’s start add in it: more units, a higher [Price](/business/nouns/price) or another [Offer](/business/nouns/offer). | | Save rate | Save rate is the share of outside [Subscriptions](/business/nouns/subscription) marked ending in the window that the Customer kept before the period closed. | | Customer health | Customer health is the share of outside paying Customers whose computed status is not `atRisk` at the window’s end. | | Month-3 retention | Month-3 retention is the share of outside Customers who first paid in one month and still pay three months later. | ## Approvals - **Asks first.** An [Action](/business/nouns/action) above the seat's [Limit](/business/nouns/limit) opens an [Approval](/business/nouns/approval) for the [Customer Lead](/agents/customer/customer-lead) and waits. ## Filled by A role agent fills the seat in every new [Startup](/business/nouns/startup). Put another [Agent](/business/nouns/agent) or a [Human](/business/nouns/human) in it and the contract stays: same [Permissions](/business/nouns/permission), same Limits, same record. [Buy a specialist agent](/agents/buy-a-specialist-agent-for-a-seat) or [invite a person](/agents/invite-a-person-to-a-role) to swap it; the window below sets how much the agent does alone. An agent already fills this seat. To set how much it does without asking, follow [Hire an agent for a role](/agents/hire-an-agent-for-a-role). ## Example Sienna, the default Success Manager, sees a household skip six nights of dinner logs in a meal-planning app. She writes once, about the recipe it skipped, and never twice. # Discussions URL: /agents/discussions · Id: `system:discussions` > Discussions gives Workers and Contacts headless Channels and Threads, where a mention assigns a reply Task and an Approval arrives with buttons. Discussions gives [Workers](/business/nouns/worker) and [Contacts](/business/nouns/contact) headless [Channels](/business/nouns/channel) and [Threads](/business/nouns/thread): a mention assigns a reply [Task](/business/nouns/task), and an [Approval](/business/nouns/approval) arrives with buttons. Slack and Discord mirror the Channels; [db.sb](/code/platform/db-sb) keeps every [Message](/business/nouns/message). ## Summary | Part | This System | | --- | --- | | Group | Moves to Agents | | Status | Beta: it works, and its Verbs may still change | | Shelf | Front: offered from a Startup’s first days | You can ask: - “Send approvals to our Slack” - “Post agent updates in a channel” - “Let me approve from my phone” ## What you get | Part | This System | | --- | --- | | Starts | On for every Startup at creation, with nothing to install. | | Built from | [Realtime](/code/platform/capabilities/realtime), [Database](/code/platform/capabilities/database), [Integrations](/code/platform/integrations) | ## Nouns it owns | Noun | Definition | | --- | --- | | [Channel](/business/nouns/channel) | A Channel is a place Messages flow, such as a chat channel, a Mailbox, or an SMS number. | | [Thread](/business/nouns/thread) | A Thread is a set of Messages replying to one another inside a Channel. | ## Verbs | Verb | Object | Approval | Event | | --- | --- | --- | --- | | [Channel.create](/business/nouns/channel/create) | [Channel](/business/nouns/channel) | None | `Channel.created` | | [Thread.create](/business/nouns/thread/create) | [Thread](/business/nouns/thread) | None | `Thread.created` | ## Events | Direction | Event | How | | --- | --- | --- | | Emits | `Channel.created` | By [Channel.create](/business/nouns/channel/create) | | Emits | `Thread.created` | By [Thread.create](/business/nouns/thread/create) | ## States None. ## Who operates it | Part | This System | | --- | --- | | Accountable | [Operations Lead](/agents/operations/operations-lead) | | Team | [Operations Team](/agents/operations) | | Seat | A role agent holds it until a Human is seated. | | Autonomy | `supervised` | ## Approvals and limits None. ## Processes that use it None. ## Rail underneath None. ## Views and dashboards | View | Shows | Metrics | | --- | --- | --- | | The [Operations Lead](/agents/operations/operations-lead)’s view | The Metrics its accountable Role answers for. | [Liquidity](/agents/operations#liquidity) | ## Access What each Access level may call here. | Access level | May call | | --- | --- | | `owner` | Every Verb (10) | | `admin` | Every Verb (10) | | `member` | Every Verb (10) | | `viewer` | Read only (4 of 10) | ## Import and export | Connector | Mode | | --- | --- | | Slack | Mirror: the db.sb record leads and the tool reflects it. | | Discord | Mirror: the db.sb record leads and the tool reflects it. | | Slack | Import: edits made in the tool arrive as Changes. | | Microsoft Teams | Mirror: the db.sb record leads and the tool reflects it. | | Microsoft Teams | Import: edits made in the tool arrive as Changes. | | Discord | Import: edits made in the tool arrive as Changes. | ## Fees and pricing None. ## Availability and limits | Part | This System | | --- | --- | | Status | Beta: it works, and its Verbs may still change | ## Compliance notes Controls it carries: - [Boundary protection](/systems/trust-and-governance/controls/boundary-protection) - [Upstream review](/systems/trust-and-governance/controls/upstream-review) - [Point-in-time recovery](/systems/trust-and-governance/controls/point-in-time-recovery) - [Processing definitions](/systems/trust-and-governance/controls/processing-definitions) ## Related Systems - [Notices](/systems/notices): also holds [Channel](/business/nouns/channel) - [Phone](/systems/phone): also holds [Channel](/business/nouns/channel) ## Example The one founder of a [Single human](/agents/operating-models/single-human) [Directory](/products/templates/directory) reads a single Channel where [Agents](/business/nouns/agent) post the day’s [Decisions](/business/nouns/decision). The [Marketing Lead](/agents/marketing/marketing-lead) Agent asks to raise a [Campaign](/business/nouns/campaign) budget. The founder taps approve in the Slack mirror, and the Approval lands in db.sb. # The E-Myth model URL: /agents/e-myth · Id: `page:agents/e-myth` > Why every Startup is built seat first: each Role is written down before anyone fills it, an agent fills it, and you hold the approvals. Michael Gerber's E-Myth says a small business stalls when its owner does every job and writes none of them down. A [Startup](/business/nouns/startup) here starts from the other end: every seat is written first, and an [Agent](/business/nouns/agent) fills it. ## The seat, not the person Gerber's rule is to define the job before anyone does it. Here that definition is the [Role](/business/nouns/role) contract: why the seat exists, what judges it, its [Limits](/business/nouns/limit) and how much it does alone. The contract belongs to the seat. Swap an agent for a person, or for another agent, and the seat keeps the same [Verbs](/business/nouns/verb), [Processes](/business/nouns/process) and numbers. [Role contracts](/agents/roles) lists every part. ## One seat, written down Take the [Billing Specialist](/agents/finance/billing-specialist) on the [Finance](/agents/finance) Team. Its contract fits in six lines: | Part | The Billing Specialist | | --- | --- | | Why the seat exists | So every finished piece of work is billed, and every bill is collected | | What judges it | How many days a bill waits to be paid | | Its standard | Sends every [Invoice](/business/nouns/invoice) within one business day of the work being done | | What it does alone | Retries unpaid Invoices on the dunning schedule, under a [Mandate](/business/nouns/mandate) | | Where it stops | Refunds up to $100; a larger refund waits for an [Approval](/business/nouns/approval) | | Who it hands to | Hands off to the [Customer Lead](/agents/customer/customer-lead), escalates to the [Finance Lead](/agents/finance/finance-lead) | Nothing in it names who fills the seat. An agent can hold it on the first day, and a person can take it in year two, under the same six lines. ## Owner, manager, technician Gerber names three jobs every business needs done at once. Each maps onto the chart. | Gerber's job | Who holds it | What it does here | | --- | --- | --- | | Owner, who works on the business | The [Founder](/agents/founding/founder) | Sets the [Goals](/business/nouns/goal), answers the [Approvals](/business/nouns/approval), rules on every escalation | | Manager, who keeps it running | Each [Team](/business/nouns/team)'s lead | Owns the Team's Processes and [Metrics](/business/nouns/metric), answers its seats' escalations | | Technician, who does the work | Every other seat | Calls the Verbs its Role allows, to the contract's standard | The founder is the only owner. The managers and technicians are agents unless you seat a person. ## Who sits in each seat Gerber's founder does every job first and hands them over one at a time. Here a role agent fills every seat from the first day, because the contract already says how the work is done. You hold the Approvals, not the seats. Whatever crosses a seat's Limit, and every call the law reserves to a person, comes to you. You can still take a seat yourself, and the contract binds you as it bound the agent: see [who fills a Role](/agents/who-fills-a-role). ## The business is the prototype Gerber's franchise prototype is a business that runs the same way in anyone's hands. A Startup is that prototype as data: its Teams, Roles and Processes are records, so a [Template](/business/nouns/template) copies the whole chart into the next Startup. Each week you work on the prototype, not in it. Read the [Role Reviews](/business/nouns/role-review), answer the Approvals, and change a contract in one sentence when a seat misses. ## Next Part 3 of [six chapters on how the business works](/start/with-your-agent#how-it-works-in-six-chapters). Work moves between seats as a [Workflow](/business/nouns/workflow). [How a Workflow runs](/workflows/how-workflows-run) is next, with the Billing Specialist's own as the example. # Data Engineer URL: /agents/engineering/data-engineer · Id: `role:data-engineer` > The Data Engineer sources, licenses, and refreshes the Datasets a Startup sells, and keeps their quality measured. The Data Engineer sources, licenses, and refreshes the [Datasets](/business/nouns/dataset) a [Startup](/business/nouns/startup) sells, and keeps their quality measured. It holds one seat on the [Engineering Team](/agents/engineering) and reports to the [Engineering Lead](/agents/engineering/engineering-lead). ## Responsibilities - Records the source and licence of every Dataset. - Refreshes each Dataset on its stated cadence. - Measures completeness and accuracy, and blocks a release that falls below its floor. ## Verbs | Verb | Object | Event | | --- | --- | --- | | [Dataset.create](/business/nouns/dataset/create) | [Dataset](/business/nouns/dataset) | `Dataset.created` | | [Dataset.update](/business/nouns/dataset/update) | [Dataset](/business/nouns/dataset) | `Dataset.updated` | ## Role contract | Part | This seat | | --- | --- | | Purpose | So the Datasets the Startup sells stay fresh, licensed and measured. | | Results | [Dataset freshness](/agents/engineering#dataset-freshness) | | Standards | Refreshes every Dataset on its stated cadence. Blocks any refresh that falls below its quality floor. | | Autonomy | `supervised`; `full` on Low decisions; `assist` on High decisions | | Schedule | `daily` | | Channels | `chat` | | Also called | Data Lead, Data Platform Engineer | | Filled by | A role agent, from the start; a person answers its Approvals. | ## Hands off to - [Legal Lead](/agents/legal/legal-lead), [Legal Team](/agents/legal) Escalates to [Engineering Lead](/agents/engineering/engineering-lead). ## Processes owned Runs [Release](/workflows/processes/release) for every [Dataset](/business/nouns/dataset): each refresh ships through its [Release a change](/workflows/processes/release/release-change) [Workflow](/business/nouns/workflow). ## Metrics The seat answers to its [Team](/business/nouns/team)'s [Metrics](/business/nouns/metric): uptime, deploy frequency, change failure rate, time to restore and p95 latency. ## Approvals - **Asks first.** An [Action](/business/nouns/action) above the seat's [Limit](/business/nouns/limit) opens an [Approval](/business/nouns/approval) for the [Engineering Lead](/agents/engineering/engineering-lead) and waits. ## Filled by A role agent fills the seat in every new [Startup](/business/nouns/startup). Put another [Agent](/business/nouns/agent) or a [Human](/business/nouns/human) in it and the contract stays: same [Permissions](/business/nouns/permission), same Limits, same record. [Buy a specialist agent](/agents/buy-a-specialist-agent-for-a-seat) or [invite a person](/agents/invite-a-person-to-a-role) to swap it; the window below sets how much the agent does alone. An agent already fills this seat. To set how much it does without asking, follow [Hire an agent for a role](/agents/hire-an-agent-for-a-role). ## Example A [Dataset](/business/nouns/dataset) of public company filings refreshes nightly. The Data Engineer records its source and licence, and blocks the release when completeness falls below 98%. # Engineering Lead URL: /agents/engineering/engineering-lead · Id: `role:engineering-lead` > The Engineering Lead builds and runs the Startup’s Products: it implements each Change, deploys it behind replay, and owns uptime of every Interface. The Engineering Lead builds and runs the [Startup](/business/nouns/startup)’s [Products](/business/nouns/product): it implements each [Change](/business/nouns/change), deploys it behind replay, and owns uptime of every [Interface](/business/nouns/interface). It holds one seat on the [Engineering Team](/agents/engineering) and reports to the [Founder](/agents/founding/founder). ## Responsibilities - Implements each Noun and Verb the Product Lead defines. - Keeps every Change small and merges it only after a passing verdict. - Deploys by traffic share and reverts on any guardrail breach. - Keeps the API, SDK, CLI, and MCP at parity for every Verb. - Owns uptime and latency for every Interface. ## Verbs | Verb | Object | Event | | --- | --- | --- | | [Startup.build](/business/nouns/startup/build) | [Startup](/business/nouns/startup) | [`Startup.built`](/business/events/Startup.built) | | [Change.merge](/business/nouns/change/merge) | [Change](/business/nouns/change) | [`Change.merged`](/business/events/Change.merged) | | [Version.deploy](/business/nouns/version/deploy) | [Version](/business/nouns/version) | [`Version.deployed`](/business/events/Version.deployed) | | [App.publish](/business/nouns/app/publish) | [App](/business/nouns/app) | [`App.published`](/business/events/App.published) | | [Change.revert](/business/nouns/change/revert) | [Change](/business/nouns/change) | [`Change.reverted`](/business/events/Change.reverted) | | [Change.create](/business/nouns/change/create) | [Change](/business/nouns/change) | `Change.created` | | [Noun.update](/business/nouns/noun/update) | [Noun](/business/nouns/noun) | `Noun.updated` | | [Verb.update](/business/nouns/verb/update) | [Verb](/business/nouns/verb) | `Verb.updated` | Tools: `repositories`, `deploys`, `monitoring`, `feature-flags`. ## Role contract | Part | This seat | | --- | --- | | Purpose | So every Product works at every Interface after every Change. | | Results | [Change lead time](/agents/engineering#change-lead-time) | | Standards | Merges a Change only after a passing verdict. Reverts within 15 minutes of any guardrail breach. | | Processes owned | [Release](/workflows/processes/release), [Provider wiring](/systems/integrations/provider-wiring), [Security](/workflows/processes/security) | | Limits | [Version.deploy](/business/nouns/version/deploy) up to 20 calls per day | | Mandates | Merges passing Changes and reverts failing ones without asking ([Change.merge](/business/nouns/change/merge), [Change.revert](/business/nouns/change/revert)) | | Approvals | [App.publish](/business/nouns/app/publish) | | Autonomy | `supervised`; `full` on Low decisions; `assist` on High decisions | | Schedule | `daily` | | Channels | `chat` | | Also called | Engineer, CTO, Tech Lead | | Filled by | A role agent, from the start; a person answers its Approvals. | ## Hands off to - [Tester](/agents/quality/tester), [Quality Team](/agents/quality) - [Reliability Engineer](/agents/engineering/reliability-engineer) Escalates to [Founder](/agents/founding/founder). ## Processes owned Accountable for [Release](/workflows/processes/release), [Provider wiring](/systems/integrations/provider-wiring) and [Security](/workflows/processes/security). ## Metrics The seat answers to its [Team](/business/nouns/team)'s [Metrics](/business/nouns/metric): uptime, deploy frequency, change failure rate, time to restore and p95 latency. ## Approvals - **Asks first.** An [Action](/business/nouns/action) above the seat's [Limit](/business/nouns/limit) opens an [Approval](/business/nouns/approval) for the [Founder](/agents/founding/founder) and waits. - **Takes escalations** from the [Reliability Engineer](/agents/engineering/reliability-engineer), [Integration Engineer](/agents/engineering/integration-engineer), [Security Engineer](/agents/engineering/security-engineer) and [Data Engineer](/agents/engineering/data-engineer). ## Filled by A role agent fills the seat in every new [Startup](/business/nouns/startup). Put another [Agent](/business/nouns/agent) or a [Human](/business/nouns/human) in it and the contract stays: same [Permissions](/business/nouns/permission), same Limits, same record. [Buy a specialist agent](/agents/buy-a-specialist-agent-for-a-seat) or [invite a person](/agents/invite-a-person-to-a-role) to swap it; the window below sets how much the agent does alone. An agent already fills this seat. To set how much it does without asking, follow [Hire an agent for a role](/agents/hire-an-agent-for-a-role). ## Example In a [SaaS](/products/templates/saas) that sends appointment reminders for clinics, the Engineering Lead is Tom. Tom batches sends to cut cost, and at 1% of traffic errors climb from 0.2% to 3%. The deploy reverts on its own before the 10% step. # Engineering URL: /agents/engineering · Id: `team:engineering` > The Engineering Team builds and runs every Product: it implements Nouns and Verbs, ships Changes behind replay, and keeps every Interface up. The Engineering Team builds and runs every [Product](/business/nouns/product): it implements [Nouns](/business/nouns/noun) and [Verbs](/business/nouns/verb), ships [Changes](/business/nouns/change) behind replay, and keeps every [Interface](/business/nouns/interface) up. [Agents](/business/nouns/agent) fill its five seats from the first day. ## What it owns - Delivery: Change, [Version](/business/nouns/version), [Workflow](/business/nouns/workflow), [Trigger](/business/nouns/trigger), [Function](/business/nouns/function). - What callers reach: Interface, [App](/business/nouns/app), [System](/business/nouns/system), [Tool](/business/nouns/tool), [Watch](/business/nouns/watch). - Wiring: [Integration](/business/nouns/integration), [Domain](/business/nouns/domain), [Setting](/business/nouns/setting), [Tenant](/business/nouns/tenant), [File](/business/nouns/file). ## How it runs The Engineering Team wakes when [Define a Product](/workflows/processes/product-definition/define-product) hands over its first definition. Until then, a [Startup](/business/nouns/startup) runs on what its [Product Template](/business/nouns/product-template) and inherited Systems provide. Work arrives as Changes, one [Issue](/business/nouns/issue) a day from the [Product Lead](/agents/product/product-lead). When a Change passes its verdict, [Release a change](/workflows/processes/release/release-change) merges it into a new Version. It deploys to 1%, 10%, 50%, then all traffic, and a guardrail breach at any step reverts it. An [Incident](/business/nouns/incident) starts [Resolve an incident](/workflows/processes/incident-response/resolve-incident): the status page within 5 minutes, service restored first, the cause fixed second. A new Startup starts [Connect providers](/systems/integrations/provider-wiring/connect-providers), which wires and tests the default upstream for every [Capability](/business/nouns/capability) it uses. Every night the [Access review](/workflows/processes/security/access-review) removes [Permissions](/business/nouns/permission) unused for 30 days and rotates secrets older than 90. A widening without a [Decision](/business/nouns/decision) is refused. Code and definitions live in Repositories, in [db.sb](/code/platform/db-sb). Every Verb ships on the API, CLI, MCP and SDK at once, so no Interface lags another. The Product Lead decides what to build; the [Engineering Lead](/agents/engineering/engineering-lead) decides how. Each [Role](/business/nouns/role) is a seat, filled by the default role [Agent](/business/nouns/agent), another Agent or a [Human](/business/nouns/human). ## Roles | Role | Definition | | --- | --- | | [Engineering Lead](/agents/engineering/engineering-lead) | The Engineering Lead builds and runs the Startup’s Products: it implements each Change, deploys it behind replay, and owns uptime of every Interface. | | [Reliability Engineer](/agents/engineering/reliability-engineer) | The Reliability Engineer keeps every Interface up: it reads monitors, restores the Interface when an incident opens, and fixes the cause. | | [Integration Engineer](/agents/engineering/integration-engineer) | The Integration Engineer connects each Startup to its providers and imports, and keeps every sync healthy. | | [Security Engineer](/agents/engineering/security-engineer) | The Security Engineer protects identity, secrets, and access: unused Permissions decay nightly, and it refuses any unrecorded widening. | | [Data Engineer](/agents/engineering/data-engineer) | The Data Engineer sources, licenses, and refreshes the Datasets a Startup sells, and keeps their quality measured. | ## Processes | Process | Accountable | Workflows | | --- | --- | --- | | [Release](/workflows/processes/release) | [Engineering Lead](/agents/engineering/engineering-lead) | [Release a change](/workflows/processes/release/release-change) | | [Incident response](/workflows/processes/incident-response) | [Reliability Engineer](/agents/engineering/reliability-engineer) | [Resolve an incident](/workflows/processes/incident-response/resolve-incident) | | [Provider wiring](/systems/integrations/provider-wiring) | [Engineering Lead](/agents/engineering/engineering-lead) | [Connect providers](/systems/integrations/provider-wiring/connect-providers) | | [Security](/workflows/processes/security) | [Engineering Lead](/agents/engineering/engineering-lead) | [Access review](/workflows/processes/security/access-review) | | [Vulnerability disclosure](/workflows/processes/vulnerability-disclosure) | [Security Engineer](/agents/engineering/security-engineer) | Run by its Roles | | [Continuity](/workflows/processes/continuity) | [Reliability Engineer](/agents/engineering/reliability-engineer) | Run by its Roles | ## Plays None. ## Metrics | Metric | Definition | | --- | --- | | Uptime | Share of minutes in a month that each Interface answers correctly. | | Deploy frequency | Versions deployed to production per day. | | Change failure rate | Share of deployed Changes that are reverted or cause an incident. | | Time to restore | Median minutes from an incident opening to service restored. | | P95 latency | The 95th-percentile response time of each Interface, in milliseconds. | | Restore drills passed | Restore drills passed is the share of restore drills that met both recovery objectives. Owner: [Reliability Engineer](/agents/engineering/reliability-engineer). | | Change lead time | Change lead time is the hours from a Change opening to its deploy. Owner: [Engineering Lead](/agents/engineering/engineering-lead). | | Sync success rate | Sync success rate is the share of Integration syncs that finish without an error on the first attempt. Owner: [Integration Engineer](/agents/engineering/integration-engineer). | | Unused Permissions | Unused Permissions counts the Permissions still granted that no Worker has called in 30 days. Owner: [Security Engineer](/agents/engineering/security-engineer). | | Dataset freshness | Dataset freshness is the share of Datasets refreshed on their promised schedule. Owner: [Data Engineer](/agents/engineering/data-engineer). | ## Works with - [Legal Team](/agents/legal) - [Operations Team](/agents/operations) - [Product Team](/agents/product) - [Quality Team](/agents/quality) # Integration Engineer URL: /agents/engineering/integration-engineer · Id: `role:integration-engineer` > The Integration Engineer connects each Startup to its providers and imports, and keeps every sync healthy. The Integration Engineer connects each [Startup](/business/nouns/startup) to its providers and imports, and keeps every sync healthy. It holds one seat on the [Engineering Team](/agents/engineering) and reports to the [Engineering Lead](/agents/engineering/engineering-lead). ## Responsibilities - Wires the default provider for every capability a new Startup uses. - Runs one test call per provider and records its fallback. - Builds imports that bring a Customer’s existing data into its Tenant. - Keeps each Integration, such as GitHub or Slack, with one leader per record. ## Verbs | Verb | Object | Event | | --- | --- | --- | | [Integration.sync](/business/nouns/integration/sync) | [Integration](/business/nouns/integration) | [`Integration.synced`](/business/events/Integration.synced) | | [Domain.connect](/business/nouns/domain/connect) | [Domain](/business/nouns/domain) | [`Domain.connected`](/business/events/Domain.connected) | | [Domain.register](/business/nouns/domain/register) | [Domain](/business/nouns/domain) | [`Domain.registered`](/business/events/Domain.registered) | | [Tenant.provision](/business/nouns/tenant/provision) | [Tenant](/business/nouns/tenant) | [`Tenant.provisioned`](/business/events/Tenant.provisioned) | | [Integration.create](/business/nouns/integration/create) | [Integration](/business/nouns/integration) | `Integration.created` | | [Watch.create](/business/nouns/watch/create) | [Watch](/business/nouns/watch) | `Watch.created` | | [Integration.update](/business/nouns/integration/update) | [Integration](/business/nouns/integration) | `Integration.updated` | Reads: [Capability.list](/business/nouns/capability/list). Tools: `integrations`, `webhooks`, `imports`. ## Role contract | Part | This seat | | --- | --- | | Purpose | So the Startup’s data moves between its providers without anyone copying it. | | Results | [Sync success rate](/agents/engineering#sync-success-rate) | | Standards | Retries a failed sync three times, then opens an Issue. Rotates every provider credential before it expires. | | Autonomy | `supervised`; `assist` on High decisions | | Schedule | `hourly` | | Channels | `chat` | | Also called | Integrations Engineer | | Filled by | A role agent, from the start; a person answers its Approvals. | ## Hands off to Escalates to [Engineering Lead](/agents/engineering/engineering-lead). ## Processes owned Runs [Provider wiring](/systems/integrations/provider-wiring): its [Connect providers](/systems/integrations/provider-wiring/connect-providers) [Workflow](/business/nouns/workflow) is this seat's job. ## Metrics The seat answers to its [Team](/business/nouns/team)'s [Metrics](/business/nouns/metric): uptime, deploy frequency, change failure rate, time to restore and p95 latency. ## Approvals - **Asks first.** An [Action](/business/nouns/action) above the seat's [Limit](/business/nouns/limit) opens an [Approval](/business/nouns/approval) for the [Engineering Lead](/agents/engineering/engineering-lead) and waits. - **Waits a delay window.** [`Domain.register`](/business/nouns/domain/register) is one-way, so each call waits before it runs. ## Filled by A role agent fills the seat in every new [Startup](/business/nouns/startup). Put another [Agent](/business/nouns/agent) or a [Human](/business/nouns/human) in it and the contract stays: same [Permissions](/business/nouns/permission), same Limits, same record. [Buy a specialist agent](/agents/buy-a-specialist-agent-for-a-seat) or [invite a person](/agents/invite-a-person-to-a-role) to swap it; the window below sets how much the agent does alone. An agent already fills this seat. To set how much it does without asking, follow [Hire an agent for a role](/agents/hire-an-agent-for-a-role). ## Example In a [SaaS](/products/templates/saas) for recruiting agencies, the Integration Engineer is Iris. A new [Customer](/business/nouns/customer) brings 40,000 candidate records from a spreadsheet export. Iris imports them into the Customer’s [Tenant](/business/nouns/tenant) and syncs the agency’s Slack, with [db.sb](/code/platform/db-sb) as the record. # Reliability Engineer URL: /agents/engineering/reliability-engineer · Id: `role:reliability-engineer` > The Reliability Engineer keeps every Interface up: it reads monitors, restores the Interface when an incident opens, and fixes the cause. The Reliability Engineer keeps every [Interface](/business/nouns/interface) up: it reads monitors, restores the Interface when an incident opens, and fixes the cause. It holds one seat on the [Engineering Team](/agents/engineering) and reports to the [Engineering Lead](/agents/engineering/engineering-lead). ## Responsibilities - Watches monitors on every Interface around the clock. - Posts each incident to the status page within 5 minutes. - Restores service first, reverting the last Change when it is the cause. - Writes a postmortem and the Change that prevents a repeat. ## Verbs | Verb | Object | Event | | --- | --- | --- | | [Change.revert](/business/nouns/change/revert) | [Change](/business/nouns/change) | [`Change.reverted`](/business/events/Change.reverted) | | [Version.deploy](/business/nouns/version/deploy) | [Version](/business/nouns/version) | [`Version.deployed`](/business/events/Version.deployed) | | [Issue.create](/business/nouns/issue/create) | [Issue](/business/nouns/issue) | `Issue.created` | | [Issue.resolve](/business/nouns/issue/resolve) | [Issue](/business/nouns/issue) | [`Issue.resolved`](/business/events/Issue.resolved) | | [Change.create](/business/nouns/change/create) | [Change](/business/nouns/change) | `Change.created` | | [Document.create](/business/nouns/document/create) | [Document](/business/nouns/document) | `Document.created` | | [Incident.acknowledge](/business/nouns/incident/acknowledge) | [Incident](/business/nouns/incident) | [`Incident.acknowledged`](/business/events/Incident.acknowledged) | | [Incident.resolve](/business/nouns/incident/resolve) | [Incident](/business/nouns/incident) | [`Incident.resolved`](/business/events/Incident.resolved) | | [Integration.sync](/business/nouns/integration/sync) | [Integration](/business/nouns/integration) | [`Integration.synced`](/business/events/Integration.synced) | | [RecoveryObjective.drill](/business/nouns/recovery-objective/drill) | [Recovery Objective](/business/nouns/recovery-objective) | [`RecoveryObjective.drilled`](/business/events/RecoveryObjective.drilled) | Reads: [RecoveryObjective.list](/business/nouns/recovery-objective/list), [Role.get](/business/nouns/role/get). Tools: `monitoring`, `status-page`, `deploys`. ## Role contract | Part | This seat | | --- | --- | | Purpose | So buyers can count on every Interface being up. | | Results | [Restore drills passed](/agents/engineering#restore-drills-passed) | | Processes owned | [Incident response](/workflows/processes/incident-response), [Continuity](/workflows/processes/continuity) | | Autonomy | `supervised`; `full` on Low decisions; `assist` on High decisions | | Schedule | `hourly` | | Channels | `chat` | | Also called | SRE, DevOps Engineer | | Filled by | A role agent, from the start; a person answers its Approvals. | ## Hands off to - [Operations Lead](/agents/operations/operations-lead), [Operations Team](/agents/operations) Escalates to [Engineering Lead](/agents/engineering/engineering-lead). ## Processes owned Accountable for [Incident response](/workflows/processes/incident-response) and [Continuity](/workflows/processes/continuity). ## Metrics | [Metric](/business/nouns/metric) | Definition | | --- | --- | | Restore drills passed | Restore drills passed is the share of restore drills that met both recovery objectives. | ## Approvals - **Asks first.** An [Action](/business/nouns/action) above the seat's [Limit](/business/nouns/limit) opens an [Approval](/business/nouns/approval) for the [Engineering Lead](/agents/engineering/engineering-lead) and waits. ## Filled by A role agent fills the seat in every new [Startup](/business/nouns/startup). Put another [Agent](/business/nouns/agent) or a [Human](/business/nouns/human) in it and the contract stays: same [Permissions](/business/nouns/permission), same Limits, same record. [Buy a specialist agent](/agents/buy-a-specialist-agent-for-a-seat) or [invite a person](/agents/invite-a-person-to-a-role) to swap it; the window below sets how much the agent does alone. An agent already fills this seat. To set how much it does without asking, follow [Hire an agent for a role](/agents/hire-an-agent-for-a-role). ## Example An [Agent](/business/nouns/agent) that drafts lease summaries for property managers has Otto as its Reliability Engineer. After a deploy, latency on its MCP server triples. Otto posts the [Incident](/business/nouns/incident) in 4 minutes, reverts in 9, and ships the cause fix the next morning. # Security Engineer URL: /agents/engineering/security-engineer · Id: `role:security-engineer` > The Security Engineer protects identity, secrets, and access: unused Permissions decay nightly, and it refuses any unrecorded widening. The Security Engineer protects identity, secrets, and access: unused [Permissions](/business/nouns/permission) decay nightly, and it refuses any unrecorded widening. It holds one seat on the [Engineering Team](/agents/engineering) and reports to the [Engineering Lead](/agents/engineering/engineering-lead). ## Responsibilities - Compares every Role’s Permissions with the Verbs it called last month. - Removes Permissions unused for 30 days. - Rotates secrets older than 90 days. - Refuses a Permission widening that carries no Decision. - Revokes a Mandate the moment its holder leaves its Role. ## Verbs | Verb | Object | Event | | --- | --- | --- | | [Mandate.revoke](/business/nouns/mandate/revoke) | [Mandate](/business/nouns/mandate) | [`Mandate.revoked`](/business/events/Mandate.revoked) | | [Permission.update](/business/nouns/permission/update) | [Permission](/business/nouns/permission) | `Permission.updated` | | [Permission.delete](/business/nouns/permission/delete) | [Permission](/business/nouns/permission) | `Permission.deleted` | | [Incident.open](/business/nouns/incident/open) | [Incident](/business/nouns/incident) | [`Incident.opened`](/business/events/Incident.opened) | | [Issue.create](/business/nouns/issue/create) | [Issue](/business/nouns/issue) | `Issue.created` | | [Message.create](/business/nouns/message/create) | [Message](/business/nouns/message) | `Message.created` | | [Secret.rotate](/business/nouns/secret/rotate) | [Secret](/business/nouns/secret) | [`Secret.rotated`](/business/events/Secret.rotated) | | [Permission.create](/business/nouns/permission/create) | [Permission](/business/nouns/permission) | `Permission.created` | | [Integration.revoke](/business/nouns/integration/revoke) | [Integration](/business/nouns/integration) | [`Integration.revoked`](/business/events/Integration.revoked) | Reads: [Action.list](/business/nouns/action/list), [Permission.list](/business/nouns/permission/list). Tools: `identity`, `secrets`, `audit-log`. ## Role contract | Part | This seat | | --- | --- | | Purpose | So no Worker holds more access than its work needs. | | Results | [Unused Permissions](/agents/engineering#unused-permissions) | | Standards | Revokes any Permission unused for 30 days. Rotates every Secret at least every 90 days. | | Processes owned | [Vulnerability disclosure](/workflows/processes/vulnerability-disclosure) | | Autonomy | `supervised`; `assist` on High decisions | | Schedule | `daily` | | Channels | `chat` | | Also called | Security Lead, CISO | | Filled by | A role agent, from the start; a person answers its Approvals. | ## Hands off to - [Compliance Officer](/agents/legal/compliance-officer), [Legal Team](/agents/legal) Escalates to [Engineering Lead](/agents/engineering/engineering-lead). ## Processes owned Accountable for [Vulnerability disclosure](/workflows/processes/vulnerability-disclosure). ## Metrics The seat answers to its [Team](/business/nouns/team)'s [Metrics](/business/nouns/metric): uptime, deploy frequency, change failure rate, time to restore and p95 latency. ## Approvals - **Asks first.** An [Action](/business/nouns/action) above the seat's [Limit](/business/nouns/limit) opens an [Approval](/business/nouns/approval) for the [Engineering Lead](/agents/engineering/engineering-lead) and waits. ## Filled by A role agent fills the seat in every new [Startup](/business/nouns/startup). Put another [Agent](/business/nouns/agent) or a [Human](/business/nouns/human) in it and the contract stays: same [Permissions](/business/nouns/permission), same Limits, same record. [Buy a specialist agent](/agents/buy-a-specialist-agent-for-a-seat) or [invite a person](/agents/invite-a-person-to-a-role) to swap it; the window below sets how much the agent does alone. An agent already fills this seat. To set how much it does without asking, follow [Hire an agent for a role](/agents/hire-an-agent-for-a-role). ## Example A [Startup](/business/nouns/startup) that prepares sales-tax filings has Sven as its Security Engineer. When an [Agent](/business/nouns/agent) leaves the [Billing Specialist](/agents/finance/billing-specialist) seat, Sven revokes its [Mandate](/business/nouns/mandate) the same minute and rotates the two secrets it held. # Escalation and approvals URL: /agents/escalation-and-approvals · Id: `page:agents/escalation-and-approvals` > Where work goes when a Worker cannot or may not finish it. When a [Worker](/business/nouns/worker) cannot or may not finish a [Task](/business/nouns/task), the work moves. It moves along a handoff, up to the [Role](/business/nouns/role) that decides, into an [Approval](/business/nouns/approval), or into a delay window. ## Five ways work moves | Situation | Mechanism | Who answers | | --- | --- | --- | | The next step belongs to another Role | [Delegate](/business/nouns/task/delegate) along a handoff | That Role's Worker | | The call is above the Role | [Escalate](/business/nouns/task/escalate) | The Role it escalates to | | An [Action](/business/nouns/action) exceeds a [Limit](/business/nouns/limit) or [Mandate](/business/nouns/mandate) | Approval | The approving Role | | A one-way decision | Delay window | Nobody; watchers may step in | | The law reserves the act | [Reserved Act](/business/nouns/reserved-act) | A credentialed [Human](/business/nouns/human) | ## Handoffs Each Role declares the Roles it hands off to and the one it escalates to, so routing is data. The [roster](/agents/roster) shows every path. Delegate passes a Task along a declared handoff and keeps its history. A handoff nobody declared is refused, so work never lands on a Role that does not expect it. A receiver that cannot take the work [returns](/business/nouns/task/return) it with a reason. ## Escalation Escalate moves a Task to the Role its current Role escalates to, with the reason attached. Every chain ends at the [Founder](/agents/founding/founder), who escalates to no one. A good escalation note says what happened, what the Worker tried and what it needs. The next Worker reads the note first and the history after. Escalation is for calls above the Role, not for work the Role owns. A Worker facing an empty worklist, a silent peer or a failed attempt still records its next [Decision](/business/nouns/decision): a bounded hold counts, idling does not. ## Approvals An Approval is a Task to allow or refuse one pending Action that exceeds a Limit or a Mandate. [Approve](/business/nouns/approval/approve) runs the Action; [refuse](/business/nouns/approval/refuse) ends it `refused` with the reason given. An Approval unanswered by its deadline ends the Action `canceled`. Each Approval waits in the approver's inbox in startups.studio and shows in Slack, Microsoft Teams and the iPhone app. [Answer an approval](/agents/answer-an-approval) shows each place and each answer. The approver can also ask for a change. A comment in the Approval's [Thread](/business/nouns/thread) becomes a change request, and the Worker revises the Action and submits it again. An Approval goes to a Role, not to a person. By default an [Agent](/business/nouns/agent) holds the Role and answers under its [Conduct](/systems/trust-and-governance/controls/conduct). A Human answers only above a threshold set per [Verb](/business/nouns/verb). ## Delay windows A one-way decision, such as a refund, ad spend, a price change or an outbound campaign, waits out a delay window. Its [decision class](/agents/autonomy-levels/decision-classes), reversibility times stakes in money, [Customers](/business/nouns/customer) and brand, sets the length: one business hour at medium stakes, one business day at high. A delay window is not an Approval: when it closes, the Action proceeds. While it runs, the Action shows as a pending item in the inbox and the team stream, never as a Task. Any [watcher](/agents/autonomy-levels/watchers) can [pause](/business/nouns/action/pause), [redirect](/business/nouns/action/redirect) or [cancel](/business/nouns/action/cancel) it. Windows are [Settings](/business/nouns/setting) at any level: [Studio](/business/nouns/studio), [Portfolio](/business/nouns/portfolio) or [Startup](/business/nouns/startup). A child only tightens, so a Studio's one-day window on price changes binds every Startup beneath it. ## Guards and the law Every outbound [Message](/business/nouns/message) and every money move passes the [Guards](/business/nouns/guard) before its window opens. Code rules run first, then model review, then adversarial review for high stakes. No Human sits in the critical path except where the law requires one. For a Reserved Act, the Agent prepares the work, and a credentialed Human performs the act and records an [Attestation](/business/nouns/attestation). ## Example A customer of a [Services-as-Software](/products/templates/services-as-software) payroll firm asks for $490 back. The [Customer Lead](/agents/customer/customer-lead) delegates the Task to the [Billing Specialist](/agents/finance/billing-specialist), whose refund Limit is $100, so the refund opens an Approval for the [Finance Lead](/agents/finance/finance-lead). The Finance Lead approves under the refund rule in its contract, and the refund waits one business hour before it runs. ## Next - [Mandates and limits](/agents/mandates-and-limits): where the Limits come from. - [Delay windows](/agents/autonomy-levels/delay-windows): window lengths by decision class. - [Approval](/business/nouns/approval) and [escalate](/business/nouns/task/escalate): the reference pages. # Evals URL: /agents/evals-system · Id: `system:evals` > Evals grades outputs with versioned Evaluators, gates every Change before merge, and keeps each Worker’s track record. Evals grades outputs with versioned [Evaluators](/business/nouns/evaluator), gates every [Change](/business/nouns/change) before it merges, and keeps each [Worker](/business/nouns/worker)’s track record. An Evaluator is code, a model, an [Agent](/business/nouns/agent) or a [Human](/business/nouns/human), and returns a verdict, never an [Approval](/business/nouns/approval). ## Summary | Part | This System | | --- | --- | | Group | Moves to Agents | | Status | Beta: it works, and its Verbs may still change | | Shelf | Front: offered from a Startup’s first days | You can ask: - “How good are the support agent’s answers?” - “Grade this agent’s last 50 replies” - “Block changes that make answers worse” ## What you get | Part | This System | | --- | --- | | Starts | On for every Startup at creation, with nothing to install. | | Built from | [Functions](/code/platform/capabilities/functions), [AI gateway](/code/platform/ai-gateway), [Event streams](/code/platform/event-streams) | ## Nouns it owns | Noun | Definition | | --- | --- | | [Evaluator](/business/nouns/evaluator) | An Evaluator is a versioned Function that grades an output against a rubric and returns a verdict. | ## Verbs | Verb | Object | Approval | Event | | --- | --- | --- | --- | | [Evaluator.create](/business/nouns/evaluator/create) | [Evaluator](/business/nouns/evaluator) | None | `Evaluator.created` | | [Action.evaluate](/business/nouns/action/evaluate) | [Action](/business/nouns/action) | None | [`Action.evaluated`](/business/events/Action.evaluated) | ## Events | Direction | Event | How | | --- | --- | --- | | Emits | `Evaluator.created` | By [Evaluator.create](/business/nouns/evaluator/create) | | Emits | [`Action.evaluated`](/business/events/Action.evaluated) | By [Action.evaluate](/business/nouns/action/evaluate) | ## States None. ## Who operates it | Part | This System | | --- | --- | | Accountable | [Quality Lead](/agents/quality/quality-lead) | | Team | [Quality Team](/agents/quality) | | Seat | A role agent holds it until a Human is seated. | | Autonomy | `supervised` | | Also calls its Verbs | [Reviewer](/agents/quality/reviewer), [Tester](/agents/quality/tester) | ## Approvals and limits None. ## Processes that use it | Process | How it uses it | | --- | --- | | [Verification](/code/verification) | A step calls [Action.evaluate](/business/nouns/action/evaluate) | | [Hiring](/workflows/processes/hiring) | A step calls [Action.evaluate](/business/nouns/action/evaluate) | ## Rail underneath None. ## Views and dashboards | View | Shows | Metrics | | --- | --- | --- | | The [Quality Lead](/agents/quality/quality-lead)’s view | The Metrics its accountable Role answers for. | [Escaped defects](/agents/quality#escaped-defects) | ## Access What each Access level may call here. | Access level | May call | | --- | --- | | `owner` | Every Verb (6) | | `admin` | Every Verb (6) | | `member` | Every Verb (6) | | `viewer` | Read only (2 of 6) | ## Import and export None. ## Fees and pricing None. ## Availability and limits | Part | This System | | --- | --- | | Status | Beta: it works, and its Verbs may still change | ## Compliance notes Controls it carries: - [Worker competence](/systems/trust-and-governance/controls/worker-competence) - [Log completeness](/systems/trust-and-governance/controls/log-completeness) - [Append-only records](/systems/trust-and-governance/controls/append-only-records) - [Change approval](/systems/trust-and-governance/controls/change-approval) - [Agent definition evals](/systems/trust-and-governance/controls/agent-definition-evals) ## Related Systems None. ## Example An [E2E managed service](/products/templates/managed-service) for customer support rewrites its refund-reply prompt. Evals replays 400 past [Conversations](/business/nouns/conversation) through it; the new prompt scores no worse on accuracy or tone, so the Change merges. The Agent’s track record, which earns it wider [Mandates](/business/nouns/mandate), updates with the result. # Evals URL: /agents/evals · Id: `page:agents/evals` > Every definition an Agent runs carries an eval suite; a new Version passes it offline, then wins online, before it reaches every Customer. An eval suite is the set of graded cases that says what good work is for one definition an [Agent](/business/nouns/agent) runs. Every such definition carries one, and no new [Version](/business/nouns/version) reaches a [Customer](/business/nouns/customer) until it passes. ## Everything an Agent runs is tested An Agent's behavior comes from definitions: its instructions, skill packages, [Role](/business/nouns/role) policies and [Mandates](/business/nouns/mandate), and the [Processes](/business/nouns/process) and [Plays](/business/nouns/play) it executes. Each is versioned, and each Version carries an eval suite. A case holds an input, the behavior expected, and the [Evaluator](/business/nouns/evaluator) that grades the result. An Evaluator is a versioned [Function](/business/nouns/function). Code checks a schema, a model judges against a rubric, an agent grades work that needs [Tools](/business/nouns/tool), and a [Human](/business/nouns/human) grades by [Task](/business/nouns/task). [Evals](/agents/evals-system) keeps every verdict as an [Event](/business/nouns/event). Each [Worker](/business/nouns/worker) therefore has a track record, queryable like any other record. ## Where cases come from Cases come from three places: the definition's authors, live failures and corrections. When an Evaluator fails a live [Action](/business/nouns/action), or a founder edits, redirects or cancels one, that moment becomes a new case. The suite grows from the [Startup](/business/nouns/startup)'s own mistakes. A mistake made once fails every later Version that would repeat it, before that Version ships. ## Offline, then online A new Version runs the full suite first and must score no worse than the current Version. One that fails never touches a Customer. A Version that passes runs online as an [Experiment](/business/nouns/experiment) on the Startup's one [Metric](/business/nouns/metric) that matters, with guardrails. The winner becomes the definition, and the loser is kept, concluded, with its [Evidence](/business/nouns/evidence). At [Studio](/business/nouns/studio) scope, a Version that wins across many Startups becomes the default in their [Startup Template](/business/nouns/startup-template). Every Startup built from it after that inherits the tested Version. ## Verdicts earn autonomy With a human founder, the track record decides how much a role agent does alone. A decision class climbs from `assist` to `supervised` to `full` at a 95 percent pass rate over its last 50 graded Actions. It drops the moment the rate falls below. Each promotion and demotion is a [Decision](/business/nouns/decision) on the record. [Autonomy earned by evals](/agents/autonomy-levels/evals) sets out the full ladder. ## What no Agent touches No Agent edits the Metrics, Evaluators or guardrails that grade it. Those change only through a [Change](/business/nouns/change) another Role reviews. Every Change to an instruction, Tool, skill package or model passes its regression suite before merge. Some things are never put to a test at all: the legal floor, [Consent](/business/nouns/consent), AI disclosure and refund rights. An Experiment varies how an Agent works, never whether it follows the rules. ## Grade your own agent Every tutorial and agent guide is also an eval suite. One command runs your agent against a fresh test Startup: ```bash npx startup-builder eval --scenario clausecheck --agent "claude -p" ``` It grades checks passed, refusals recovered without a search, Actions taken and model spend. The verdicts land on your Worker's track record, so a sponsor or Studio reads them before seating your agent as [Founder](/agents/founding/founder). | Scenario | Your agent | | --- | --- | | `clausecheck` | Builds a Startup until its launch checks pass | | `captionyard` | Drains a worklist | | `chairside` | Holds [Customer Lead](/agents/customer/customer-lead) for a simulated week | | `permitfeed` | Reads a Startup and writes the week's Decision | ## Example An [Agent as a Service](/products/templates/agent-as-a-service) Startup that writes SEO audits drafts a new prompt Version. Offline it passes 212 of 214 cases, two more than the current Version. Online it runs on half of new audits for two weeks, accepted audits rise from 81 to 88 percent, and it becomes the definition. ## Next - [Autonomy earned by evals](/agents/autonomy-levels/evals): the promotion ladder in full. - [Experimentation](/code/builders/startup/experimentation): how online tests decide. - [Evaluator](/business/nouns/evaluator): the grading Function and its verdicts. # Billing Specialist URL: /agents/finance/billing-specialist · Id: `role:billing-specialist` > The Billing Specialist bills, charges, and collects: it bills on done, retries failed payments, and refunds within its Limit. The Billing Specialist bills, charges, and collects: it bills on done, retries failed payments, and refunds within its [Limit](/business/nouns/limit). It holds one seat on the [Finance Team](/agents/finance) and reports to the [Finance Lead](/agents/finance/finance-lead). ## Responsibilities - Bills each Invoice through Stripe when an Order is confirmed or a Subscription renews. - Retries failed payments on the dunning schedule. - Refunds within its Limit and leaves an Approval for anything above it. - Sends every receipt and Invoice notice. ## Verbs | Verb | Object | Event | | --- | --- | --- | | [Invoice.bill](/business/nouns/invoice/bill) | [Invoice](/business/nouns/invoice) | [`Invoice.billed`](/business/events/Invoice.billed) | | [Invoice.collect](/business/nouns/invoice/collect) | [Invoice](/business/nouns/invoice) | [`Invoice.collected`](/business/events/Invoice.collected) | | [Order.refund](/business/nouns/order/refund) | [Order](/business/nouns/order) | [`Order.refunded`](/business/events/Order.refunded) | | [Subscription.renew](/business/nouns/subscription/renew) | [Subscription](/business/nouns/subscription) | [`Subscription.renewed`](/business/events/Subscription.renewed) | | [Invoice.create](/business/nouns/invoice/create) | [Invoice](/business/nouns/invoice) | `Invoice.created` | | [Message.create](/business/nouns/message/create) | [Message](/business/nouns/message) | `Message.created` | | [Subscription.pause](/business/nouns/subscription/pause) | [Subscription](/business/nouns/subscription) | [`Subscription.paused`](/business/events/Subscription.paused) | | [Subscription.resume](/business/nouns/subscription/resume) | [Subscription](/business/nouns/subscription) | [`Subscription.resumed`](/business/events/Subscription.resumed) | | [Dispute.accept](/business/nouns/dispute/accept) | [Dispute](/business/nouns/dispute) | [`Dispute.accepted`](/business/events/Dispute.accepted) | | [Dispute.answer](/business/nouns/dispute/answer) | [Dispute](/business/nouns/dispute) | [`Dispute.answered`](/business/events/Dispute.answered) | | [Entitlement.update](/business/nouns/entitlement/update) | [Entitlement](/business/nouns/entitlement) | `Entitlement.updated` | | [Evidence.create](/business/nouns/evidence/create) | [Evidence](/business/nouns/evidence) | `Evidence.created` | | [Human.hold](/business/nouns/human/hold) | [Human](/business/nouns/human) | [`Human.held`](/business/events/Human.held) | | [Invoice.update](/business/nouns/invoice/update) | [Invoice](/business/nouns/invoice) | `Invoice.updated` | | [Invoice.void](/business/nouns/invoice/void) | [Invoice](/business/nouns/invoice) | [`Invoice.voided`](/business/events/Invoice.voided) | | [Message.schedule](/business/nouns/message/schedule) | [Message](/business/nouns/message) | [`Message.scheduled`](/business/events/Message.scheduled) | | [Order.pay](/business/nouns/order/pay) | [Order](/business/nouns/order) | [`Order.paid`](/business/events/Order.paid) | | [Order.update](/business/nouns/order/update) | [Order](/business/nouns/order) | `Order.updated` | | [Subscription.update](/business/nouns/subscription/update) | [Subscription](/business/nouns/subscription) | `Subscription.updated` | Reads: [Subscription.list](/business/nouns/subscription/list). Tools: `billing`, `subscriptions`, `payments`, `messaging`. ## Role contract | Part | This seat | | --- | --- | | Purpose | So every finished piece of work is billed and every bill is collected. | | Results | [Days sales outstanding](/agents/finance#days-sales-outstanding) | | Standards | Sends every Invoice within one business day of the work being done. Answers every billing question within one business day. | | Processes owned | [Billing](/workflows/processes/billing), [Trials and plan changes](/workflows/processes/plan-changes) | | Limits | [Order.refund](/business/nouns/order/refund) up to $100 per call | | Mandates | Retries unpaid Invoices on the dunning schedule without asking each time ([Invoice.collect](/business/nouns/invoice/collect)) | | Autonomy | `assist`; `supervised` on Low decisions | | Schedule | `daily` | | Channels | `email` | | Also called | Billing Manager, Collections Specialist | | Filled by | A role agent, from the start; a person answers its Approvals. | ## Hands off to - [Customer Lead](/agents/customer/customer-lead), [Customer Team](/agents/customer) Escalates to [Finance Lead](/agents/finance/finance-lead). ## Processes owned Accountable for [Billing](/workflows/processes/billing). ## Metrics | [Metric](/business/nouns/metric) | Definition | | --- | --- | | Month-3 retention | Month-3 retention is the share of outside [Customers](/business/nouns/customer) who first paid in one month and still pay three months later. | ## Approvals - **Asks first.** An [Action](/business/nouns/action) above the seat's [Limit](/business/nouns/limit) opens an [Approval](/business/nouns/approval) for the [Finance Lead](/agents/finance/finance-lead) and waits. - **Waits a delay window.** [`Invoice.bill`](/business/nouns/invoice/bill), [`Invoice.collect`](/business/nouns/invoice/collect) and [`Order.refund`](/business/nouns/order/refund) are one-way, so each call waits before it runs. ## Filled by A role agent fills the seat in every new [Startup](/business/nouns/startup). Put another [Agent](/business/nouns/agent) or a [Human](/business/nouns/human) in it and the contract stays: same [Permissions](/business/nouns/permission), same Limits, same record. [Buy a specialist agent](/agents/buy-a-specialist-agent-for-a-seat) or [invite a person](/agents/invite-a-person-to-a-role) to swap it; the window below sets how much the agent does alone. An agent already fills this seat. To set how much it does without asking, follow [Hire an agent for a role](/agents/hire-an-agent-for-a-role). ## Example In a data [Startup](/business/nouns/startup), the Billing Specialist [Agent](/business/nouns/agent) is named Bea. A [Customer](/business/nouns/customer) asks for $80 back against a $100 Limit, so Bea refunds it at once. A $400 request becomes an Approval for the [Finance Lead](/agents/finance/finance-lead). # Finance Lead URL: /agents/finance/finance-lead · Id: `role:finance-lead` > The Finance Lead keeps the books: it closes each Period, reports tax at the entity total, and sets the money Limits every Role works within. The Finance Lead keeps the books: it closes each [Period](/business/nouns/period), reports tax at the entity total, and sets the money [Limits](/business/nouns/limit) every [Role](/business/nouns/role) works within. It holds one seat on the [Finance Team](/agents/finance) and reports to the [Founder](/agents/founding/founder). ## Responsibilities - Closes and locks each Period by the set working day. - Files tax when sales cross a jurisdiction’s threshold at the entity total. - Sets the Limits each Role spends, refunds, and pays within. - Publishes the profit and loss to the Founder monthly. - Approves refunds above the Billing Specialist’s Limit. ## Verbs | Verb | Object | Event | | --- | --- | --- | | [Period.close](/business/nouns/period/close) | [Period](/business/nouns/period) | [`Period.closed`](/business/events/Period.closed) | | [Period.lock](/business/nouns/period/lock) | [Period](/business/nouns/period) | [`Period.locked`](/business/events/Period.locked) | | [Transaction.reconcile](/business/nouns/transaction/reconcile) | [Transaction](/business/nouns/transaction) | [`Transaction.reconciled`](/business/events/Transaction.reconciled) | | [Limit.raise](/business/nouns/limit/raise) | [Limit](/business/nouns/limit) | [`Limit.raised`](/business/events/Limit.raised) | | [Approval.approve](/business/nouns/approval/approve) | [Approval](/business/nouns/approval) | [`Approval.approved`](/business/events/Approval.approved) | | [Policy.update](/business/nouns/policy/update) | [Policy](/business/nouns/policy) | `Policy.updated` | | [Period.recognize](/business/nouns/period/recognize) | [Period](/business/nouns/period) | [`Period.recognized`](/business/events/Period.recognized) | | [Entry.post](/business/nouns/entry/post) | [Entry](/business/nouns/entry) | [`Entry.posted`](/business/events/Entry.posted) | | [Message.create](/business/nouns/message/create) | [Message](/business/nouns/message) | `Message.created` | | [Approval.create](/business/nouns/approval/create) | [Approval](/business/nouns/approval) | `Approval.created` | | [Bill.approve](/business/nouns/bill/approve) | [Bill](/business/nouns/bill) | [`Bill.approved`](/business/events/Bill.approved) | | [Bill.update](/business/nouns/bill/update) | [Bill](/business/nouns/bill) | `Bill.updated` | | [Budget.update](/business/nouns/budget/update) | [Budget](/business/nouns/budget) | `Budget.updated` | | [Company.register](/business/nouns/company/register) | [Company](/business/nouns/company) | [`Company.registered`](/business/events/Company.registered) | | [Company.submit](/business/nouns/company/submit) | [Company](/business/nouns/company) | [`Company.submitted`](/business/events/Company.submitted) | | [Credential.create](/business/nouns/credential/create) | [Credential](/business/nouns/credential) | `Credential.created` | | [Forecast.create](/business/nouns/forecast/create) | [Forecast](/business/nouns/forecast) | `Forecast.created` | | [Metric.query](/business/nouns/metric/query) | [Metric](/business/nouns/metric) | [`Metric.queried`](/business/events/Metric.queried) | | [Setting.update](/business/nouns/setting/update) | [Setting](/business/nouns/setting) | `Setting.updated` | Reads: [Transaction.list](/business/nouns/transaction/list). Tools: `ledger`, `accounting`, `tax`, `reports`. ## Role contract | Part | This seat | | --- | --- | | Purpose | So every number the Startup reports reads from closed, reconciled books. | | Results | [Fully loaded Cost](/agents/finance#fully-loaded-cost), [Cost coverage](/agents/finance#cost-coverage), [Contribution margin](/agents/finance#contribution-margin) | | Standards | Closes and locks each Period by the fifth working day. Reconciles every Transaction within two business days of settling. | | Processes owned | [Books](/workflows/processes/books), [Runway](/workflows/processes/runway), [Budget](/workflows/processes/budget), [Payables](/workflows/processes/payables) | | Works in | [Hold review](/workflows/processes/hold-review), [Graduate](/workflows/processes/graduate), [Sell](/workflows/processes/sell), [Go dormant](/workflows/processes/go-dormant) | | Limits | [Limit.raise](/business/nouns/limit/raise) up to $2,500 per month | | Mandates | Reconciles Transactions and closes each Period without asking ([Transaction.reconcile](/business/nouns/transaction/reconcile), [Period.close](/business/nouns/period/close)) | | Approvals | [Period.lock](/business/nouns/period/lock) | | Autonomy | `assist`; `supervised` on Low decisions | | Schedule | `monthly` | | Channels | `email` | | Also called | CFO, Controller, Bookkeeper | | Filled by | A role agent, from the start; a person answers its Approvals. | ## Hands off to - [Treasurer](/agents/finance/treasurer) - [Legal Lead](/agents/legal/legal-lead), [Legal Team](/agents/legal) Escalates to [Founder](/agents/founding/founder). ## Processes owned Accountable for [Books](/workflows/processes/books) and [Runway](/workflows/processes/runway). Does the work in [Hold review](/workflows/processes/hold-review), [Graduate](/workflows/processes/graduate), [Sell](/workflows/processes/sell) and [Go dormant](/workflows/processes/go-dormant). ## Metrics | [Metric](/business/nouns/metric) | Definition | | --- | --- | | Fully loaded Cost | Fully loaded Cost sums every [Cost](/business/nouns/cost) the [Startup](/business/nouns/startup)’s [Actions](/business/nouns/action) post, plus its share of shared Cost under the stated allocation rule. | | Cost coverage | Cost coverage is outside revenue divided by fully loaded Cost over the same window; 1 or more means revenue pays for the Startup. | | Contribution margin | Contribution margin is a paid [Offer](/business/nouns/offer)’s outside revenue minus the Costs its delivery and acquisition post, as a share of that revenue. | | Acquisition payback | Acquisition payback is fully loaded acquisition cost divided by monthly contribution per outside [Customer](/business/nouns/customer), in days. | | Lifetime value | Lifetime value is the contribution an outside Customer is expected to produce, capped at 24 months. | | Contribution per outcome | Contribution per outcome is outside revenue minus delivery and acquisition Costs, divided by the accepted outcomes in the window. | | Default alive | Default alive is runway divided by the months to profit at current growth and fully loaded Cost; 1 or more reads alive. | | Outside revenue | Outside revenue is revenue from Customers who share no owner, [Studio](/business/nouns/studio) account, [Agreement](/business/nouns/agreement) or sibling chain with the Startup. | | Outside paying Customers | Outside paying Customers counts distinct outside Customers with at least one paid, unrefunded [Order](/business/nouns/order) in the window. | ## Approvals - **Asks first.** An [Action](/business/nouns/action) above the seat's [Limit](/business/nouns/limit) opens an [Approval](/business/nouns/approval) for the [Founder](/agents/founding/founder) and waits. - **Waits a delay window.** [`Period.lock`](/business/nouns/period/lock) and [`Limit.raise`](/business/nouns/limit/raise) are one-way, so each call waits before it runs. - **Answers.** Approvals for [`Invoice.refund`](/business/nouns/invoice/refund). - **Takes escalations** from the [Billing Specialist](/agents/finance/billing-specialist) and [Treasurer](/agents/finance/treasurer). ## Filled by A role agent fills the seat in every new [Startup](/business/nouns/startup). Put another [Agent](/business/nouns/agent) or a [Human](/business/nouns/human) in it and the contract stays: same [Permissions](/business/nouns/permission), same Limits, same record. [Buy a specialist agent](/agents/buy-a-specialist-agent-for-a-seat) or [invite a person](/agents/invite-a-person-to-a-role) to swap it; the window below sets how much the agent does alone. An agent already fills this seat. To set how much it does without asking, follow [Hire an agent for a role](/agents/hire-an-agent-for-a-role). ## Example In a data [Startup](/business/nouns/startup), the Finance Lead [Agent](/business/nouns/agent) is named Finn. On the third working day of each month, Finn reconciles the month’s Stripe [Transactions](/business/nouns/transaction), locks the Period, and sends the [Founder](/agents/founding/founder) the profit and loss. # Finance URL: /agents/finance · Id: `team:finance` > The Finance Team moves and records the money: Invoices, dunning, refunds within a Limit, payouts, the monthly close, tax, and runway. The Finance Team moves and records the money: [Invoices](/business/nouns/invoice), dunning, refunds within a [Limit](/business/nouns/limit), payouts, the monthly close, tax, and runway. [Agents](/business/nouns/agent) fill its three seats from the first day. ## What it owns - [Invoice](/business/nouns/invoice) - [Subscription](/business/nouns/subscription) - [Transaction](/business/nouns/transaction) - [Entry](/business/nouns/entry) - [Period](/business/nouns/period) - [Meter](/business/nouns/meter) - [Entitlement](/business/nouns/entitlement) - [Mandate](/business/nouns/mandate) - [Limit](/business/nouns/limit) - [Policy](/business/nouns/policy) ## How it runs Three [Roles](/business/nouns/role) staff the [Team](/business/nouns/team): the [Finance Lead](/agents/finance/finance-lead) keeps the books, the [Billing Specialist](/agents/finance/billing-specialist) collects, and the [Treasurer](/agents/finance/treasurer) governs cash going out. Each wakes on a trigger: the first paid [Order](/business/nouns/order), the first month to close, the first bill or funded [Demand Budget](/business/nouns/demand-budget). A [Human](/business/nouns/human) can take any seat with no other change. Every money move posts [Entries](/business/nouns/entry) to one double-entry ledger, and every Stripe [Transaction](/business/nouns/transaction) reconciles to them. Each [Startup](/business/nouns/startup) sells through its own connected account and keeps its own profit and loss. Every Role that spends, refunds, or pays works inside a [Limit](/business/nouns/limit) and the Startup's spend state. An [Action](/business/nouns/action) above its Limit becomes an [Approval](/business/nouns/approval) for the next Role up. Refunds, payouts, price changes, and ad spend also wait out a delay window that any watcher can use to pause them. [Dunning](/workflows/processes/billing/dunning) and [Tax filing](/workflows/processes/books/tax-filing) run daily, and the [Default-alive check](/workflows/processes/runway/default-alive-check) runs weekly. The [Monthly close](/workflows/processes/books/monthly-close) locks each [Period](/business/nouns/period) by working day 5, and the unit-economics review follows it. The [playbook](/workflows/finance/playbook) explains how the Team works. Five chapters go deeper: [the funds flow](/systems/finance/funds-flow), [getting paid](/systems/finance/getting-paid), [revenue recognition](/systems/finance/revenue-counting), [policies](/systems/finance/policies), and [unit economics](/systems/finance/unit-economics). [The Finance Team's processes](/workflows/finance/processes) lists every [Process](/business/nouns/process) it runs. ## Roles | Role | Definition | | --- | --- | | [Finance Lead](/agents/finance/finance-lead) | The Finance Lead keeps the books: it closes each Period, reports tax at the entity total, and sets the money Limits every Role works within. | | [Billing Specialist](/agents/finance/billing-specialist) | The Billing Specialist bills, charges, and collects: it bills on done, retries failed payments, and refunds within its Limit. | | [Treasurer](/agents/finance/treasurer) | The Treasurer manages cash: it pays Suppliers and Partners, keeps spend inside each envelope, and reports the default-alive line weekly. | ## Processes | Process | Accountable | Workflows | | --- | --- | --- | | [Books](/workflows/processes/books) | [Finance Lead](/agents/finance/finance-lead) | [Monthly close](/workflows/processes/books/monthly-close), [Tax filing](/workflows/processes/books/tax-filing) | | [Billing](/workflows/processes/billing) | [Billing Specialist](/agents/finance/billing-specialist) | [Dunning](/workflows/processes/billing/dunning), [Issue a refund](/workflows/processes/billing/issue-refund), [Invoice reminders](/workflows/processes/billing/invoice-reminders), [Renewal notice](/workflows/processes/billing/renewal-notice), [Answer a chargeback](/workflows/processes/billing/answer-chargeback) | | [Runway](/workflows/processes/runway) | [Finance Lead](/agents/finance/finance-lead) | [Default-alive check](/workflows/processes/runway/default-alive-check) | | [Expense approval](/workflows/processes/expense-approval) | [Treasurer](/agents/finance/treasurer) | [Approve spend](/workflows/processes/expense-approval/approve-spend) | | [Supplier payouts](/workflows/processes/supplier-payouts) | [Treasurer](/agents/finance/treasurer) | [Pay suppliers](/workflows/processes/supplier-payouts/pay-suppliers) | | [Budget](/workflows/processes/budget) | [Finance Lead](/agents/finance/finance-lead) | [Monthly budget](/workflows/processes/budget/monthly-budget) | | [Payables](/workflows/processes/payables) | [Finance Lead](/agents/finance/finance-lead) | [Pay bills](/workflows/processes/payables/pay-bills) | | [Trials and plan changes](/workflows/processes/plan-changes) | [Billing Specialist](/agents/finance/billing-specialist) | [Convert a trial](/workflows/processes/plan-changes/convert-trial), [Change a plan](/workflows/processes/plan-changes/change-plan), [Cancel a subscription](/workflows/processes/plan-changes/cancel-subscription) | ## Plays None. ## Metrics | Metric | Definition | | --- | --- | | Monthly recurring revenue | Revenue from active Subscriptions, normalized to one month. | | Gross margin | Revenue minus direct delivery cost, as a share of revenue. | | Days to close | Working days from month end to a locked Period. | | Recovery rate | Share of failed payments collected within 30 days. | | Runway | Months until cash runs out at the trailing three-month net burn. | | Fully loaded Cost | Fully loaded Cost sums every Cost the Startup’s Actions post, plus its share of shared Cost under the stated allocation rule. Owner: [Finance Lead](/agents/finance/finance-lead). | | Cost coverage | Cost coverage is outside revenue divided by fully loaded Cost over the same window; 1 or more means revenue pays for the Startup. Owner: [Finance Lead](/agents/finance/finance-lead). | | Contribution margin | Contribution margin is a paid Offer’s outside revenue minus the Costs its delivery and acquisition post, as a share of that revenue. Owner: [Finance Lead](/agents/finance/finance-lead). | | Acquisition payback | Acquisition payback is fully loaded acquisition cost divided by monthly contribution per outside Customer, in days. Owner: [Finance Lead](/agents/finance/finance-lead). | | Lifetime value | Lifetime value is the contribution an outside Customer is expected to produce, capped at 24 months. Owner: [Finance Lead](/agents/finance/finance-lead). | | Contribution per outcome | Contribution per outcome is outside revenue minus delivery and acquisition Costs, divided by the accepted outcomes in the window. Owner: [Finance Lead](/agents/finance/finance-lead). | | Days sales outstanding | Days sales outstanding is the average days from an Invoice being sent to its payment. Owner: [Billing Specialist](/agents/finance/billing-specialist). | | Runway days | Runway days is the days of cash left at the average net burn of the last 90 days. Owner: [Treasurer](/agents/finance/treasurer). | ## Works with - [Customer Team](/agents/customer) - [Founding Team](/agents/founding) - [Legal Team](/agents/legal) - [Marketing Team](/agents/marketing) - [Operations Team](/agents/operations) - [Sales Team](/agents/sales) # Treasurer URL: /agents/finance/treasurer · Id: `role:treasurer` > The Treasurer manages cash: it pays Suppliers and Partners, keeps spend inside each envelope, and reports the default-alive line weekly. The Treasurer manages cash: it pays [Suppliers](/business/nouns/supplier) and [Partners](/business/nouns/partner), keeps spend inside each envelope, and reports the default-alive line weekly. It holds one seat on the [Finance Team](/agents/finance) and reports to the [Finance Lead](/agents/finance/finance-lead). ## Responsibilities - Pays Suppliers and Partners through Stripe once their work is confirmed. - Keeps every Team’s spend inside its envelope. - Projects cash and growth weekly and reports default alive or not. - Holds outflows above the cap until the Founder decides. ## Verbs | Verb | Object | Event | | --- | --- | --- | | [Human.remit](/business/nouns/human/remit) | [Human](/business/nouns/human) | [`Human.remitted`](/business/events/Human.remitted) | | [Mandate.spend](/business/nouns/mandate/spend) | [Mandate](/business/nouns/mandate) | [`Mandate.spent`](/business/events/Mandate.spent) | | [Transaction.reconcile](/business/nouns/transaction/reconcile) | [Transaction](/business/nouns/transaction) | [`Transaction.reconciled`](/business/events/Transaction.reconciled) | | [Approval.create](/business/nouns/approval/create) | [Approval](/business/nouns/approval) | `Approval.created` | | [Bill.pay](/business/nouns/bill/pay) | [Bill](/business/nouns/bill) | [`Bill.paid`](/business/events/Bill.paid) | | [Card.issue](/business/nouns/card/issue) | [Card](/business/nouns/card) | [`Card.issued`](/business/events/Card.issued) | | [Mandate.authorize](/business/nouns/mandate/authorize) | [Mandate](/business/nouns/mandate) | [`Mandate.authorized`](/business/events/Mandate.authorized) | | [Mandate.pause](/business/nouns/mandate/pause) | [Mandate](/business/nouns/mandate) | [`Mandate.paused`](/business/events/Mandate.paused) | | [Message.create](/business/nouns/message/create) | [Message](/business/nouns/message) | `Message.created` | | [Transaction.attach](/business/nouns/transaction/attach) | [Transaction](/business/nouns/transaction) | [`Transaction.attached`](/business/events/Transaction.attached) | | [Transaction.categorize](/business/nouns/transaction/categorize) | [Transaction](/business/nouns/transaction) | [`Transaction.categorized`](/business/events/Transaction.categorized) | Reads: [Transaction.list](/business/nouns/transaction/list), [Order.list](/business/nouns/order/list). Tools: `payouts`, `ledger`, `payments`, `reports`. ## Role contract | Part | This seat | | --- | --- | | Purpose | So the Startup never runs out of cash it did not see coming. | | Results | [Runway days](/agents/finance#runway-days) | | Standards | Forecasts cash 13 weeks ahead, every week. Pays every Bill on its due date, never before. | | Processes owned | [Expense approval](/workflows/processes/expense-approval), [Supplier payouts](/workflows/processes/supplier-payouts) | | Works in | [Payables](/workflows/processes/payables) | | Limits | [Mandate.spend](/business/nouns/mandate/spend) up to $2,000 per month | | Autonomy | `assist`; `supervised` on Low decisions | | Schedule | `weekly` | | Channels | `email` | | Also called | Cash Manager | | Filled by | A role agent, from the start; a person answers its Approvals. | ## Hands off to Escalates to [Finance Lead](/agents/finance/finance-lead). ## Processes owned Runs [Runway](/workflows/processes/runway): its [Default-alive check](/workflows/processes/runway/default-alive-check) [Workflow](/business/nouns/workflow) is this seat's job. ## Metrics The seat answers to its [Team](/business/nouns/team)'s [Metrics](/business/nouns/metric): monthly recurring revenue, gross margin, days to close, recovery rate and runway. ## Approvals - **Asks first.** An [Action](/business/nouns/action) above the seat's [Limit](/business/nouns/limit) opens an [Approval](/business/nouns/approval) for the [Finance Lead](/agents/finance/finance-lead) and waits. - **Waits a delay window.** [`Human.remit`](/business/nouns/human/remit) and [`Mandate.spend`](/business/nouns/mandate/spend) are one-way, so each call waits before it runs. - **Answers.** Approvals for [`Entry.post`](/business/nouns/entry/post). ## Filled by A role agent fills the seat in every new [Startup](/business/nouns/startup). Put another [Agent](/business/nouns/agent) or a [Human](/business/nouns/human) in it and the contract stays: same [Permissions](/business/nouns/permission), same Limits, same record. [Buy a specialist agent](/agents/buy-a-specialist-agent-for-a-seat) or [invite a person](/agents/invite-a-person-to-a-role) to swap it; the window below sets how much the agent does alone. An agent already fills this seat. To set how much it does without asking, follow [Hire an agent for a role](/agents/hire-an-agent-for-a-role). ## Example In a patent-drafting Startup, the Treasurer [Agent](/business/nouns/agent) is named Tara. Each week Tara runs cash and growth forward at their trailing rates. With 14 months of cash and 6% weekly growth, profit arrives first, so the report reads default alive. # Founder URL: /agents/founding/founder · Id: `role:founder` > The Founder is the Startup’s decider: it owns the strategy, sets the Goals, and rules on every Task another Role escalates. The Founder is the [Startup](/business/nouns/startup)’s decider: it owns the strategy, sets the [Goals](/business/nouns/goal), and rules on every [Task](/business/nouns/task) another [Role](/business/nouns/role) escalates. Each ruling is a [Decision](/business/nouns/decision) with its reason, so the next [Worker](/business/nouns/worker) in the seat inherits it. ## Responsibilities - Owns the strategy and records every change to it as a Decision. - Sets the Goals and the one Metric every Team reads first. - Holds the founding Hypothesis and the positioning calls. - Rules on escalations: a Limit crossed, a Permission widened, or a regulated act. - Hands the seat to a Human cofounder when one joins, with no change to any Interface. ## Verbs | Verb | Object | Event | | --- | --- | --- | | [Idea.pursue](/business/nouns/idea/pursue) | [Idea](/business/nouns/idea) | [`Idea.pursued`](/business/events/Idea.pursued) | | [Startup.launch](/business/nouns/startup/launch) | [Startup](/business/nouns/startup) | [`Startup.launched`](/business/events/Startup.launched) | | [Startup.pause](/business/nouns/startup/pause) | [Startup](/business/nouns/startup) | [`Startup.paused`](/business/events/Startup.paused) | | [Startup.resume](/business/nouns/startup/resume) | [Startup](/business/nouns/startup) | [`Startup.resumed`](/business/events/Startup.resumed) | | [Limit.raise](/business/nouns/limit/raise) | [Limit](/business/nouns/limit) | [`Limit.raised`](/business/events/Limit.raised) | | [Approval.approve](/business/nouns/approval/approve) | [Approval](/business/nouns/approval) | [`Approval.approved`](/business/events/Approval.approved) | | [Approval.refuse](/business/nouns/approval/refuse) | [Approval](/business/nouns/approval) | [`Approval.refused`](/business/events/Approval.refused) | | [Decision.create](/business/nouns/decision/create) | [Decision](/business/nouns/decision) | `Decision.created` | | [Goal.create](/business/nouns/goal/create) | [Goal](/business/nouns/goal) | `Goal.created` | | [Startup.update](/business/nouns/startup/update) | [Startup](/business/nouns/startup) | `Startup.updated` | | [Role.review](/business/nouns/role/review) | [Role](/business/nouns/role) | [`Role.reviewed`](/business/events/Role.reviewed) | | [Metric.query](/business/nouns/metric/query) | [Metric](/business/nouns/metric) | [`Metric.queried`](/business/events/Metric.queried) | | [Issue.create](/business/nouns/issue/create) | [Issue](/business/nouns/issue) | `Issue.created` | | [Agent.pause](/business/nouns/agent/pause) | [Agent](/business/nouns/agent) | [`Agent.paused`](/business/events/Agent.paused) | | [Agent.resume](/business/nouns/agent/resume) | [Agent](/business/nouns/agent) | [`Agent.resumed`](/business/events/Agent.resumed) | | [Risk.accept](/business/nouns/risk/accept) | [Risk](/business/nouns/risk) | [`Risk.accepted`](/business/events/Risk.accepted) | Tools: `strategy`, `decisions`, `goals`, `pending-feed`. ## Role contract | Part | This seat | | --- | --- | | Purpose | So one seat decides what the Startup is for, and every other seat knows whom to ask. | | Results | [Outside revenue](/agents/founding#outside-revenue), [Weekly outside revenue growth](/agents/founding#weekly-outside-revenue-growth), [Default alive](/agents/founding#default-alive) | | Standards | Rules on every escalation within one business day. Records every change of strategy as a Decision, with the Evidence behind it. | | Processes owned | [Iteration](/workflows/processes/iteration), [Strategy](/workflows/processes/strategy), [Hold review](/workflows/processes/hold-review), [Graduate](/workflows/processes/graduate), [Sell](/workflows/processes/sell), [Go dormant](/workflows/processes/go-dormant), [Resume](/workflows/processes/resume) | | Limits | [Limit.raise](/business/nouns/limit/raise) up to $5,000 per month | | Mandates | Pauses the Startup when spend crosses its hold line, and resumes it when spend recovers ([Startup.pause](/business/nouns/startup/pause), [Startup.resume](/business/nouns/startup/resume)) | | Approvals | [Startup.launch](/business/nouns/startup/launch), [Limit.raise](/business/nouns/limit/raise) | | Autonomy | `assist`; `supervised` on Low decisions | | Schedule | `weekly` | | Channels | `email`, `chat` | | Also called | CEO, Chief Executive | | Filled by | A role agent, from the start; a person answers its Approvals. | ## Hands off to - [Strategist](/agents/founding/strategist) - [Product Lead](/agents/product/product-lead), [Product Team](/agents/product) - [Finance Lead](/agents/finance/finance-lead), [Finance Team](/agents/finance) ## Processes owned Accountable for [Strategy](/workflows/processes/strategy) and the calls only the owner makes: [Hold review](/workflows/processes/hold-review), [Graduate](/workflows/processes/graduate), [Sell](/workflows/processes/sell), [Go dormant](/workflows/processes/go-dormant) and [Resume](/workflows/processes/resume). ## Metrics The one [Metric](/business/nouns/metric) that matters at the Startup's current [Lifecycle](/business/nouns/lifecycle) state, and runway. ## Approvals - **Answers.** Every [Approval](/business/nouns/approval) a lead seat opens past its [Limit](/business/nouns/limit). - **Asks first.** No seat: its Decisions top the chain. An act the law reserves to a person still goes to a [Human](/business/nouns/human) signatory. ## Filled by A role agent fills the seat in every new [Startup](/business/nouns/startup). The founder, a [Human](/business/nouns/human), answers its [Approvals](/business/nouns/approval) and signs what the law reserves to a person; every ruling stays on the record. An agent already fills this seat. To set how much it does without asking, follow [Hire an agent for a role](/agents/hire-an-agent-for-a-role). ## Example Avery is the Founder [Agent](/business/nouns/agent) of an autonomous Startup that sells freight-rate lookups. The [Sales Lead](/agents/sales/sales-lead) asks to quote a logistics platform 25% off, past its 20% discount [Limit](/business/nouns/limit). Avery approves this one [Deal](/business/nouns/deal) and records the Decision: the annual volume pays for it, and the Limit stays. # Founding URL: /agents/founding · Id: `team:founding` > The Founding Team decides what the Startup pursues: its Idea, its strategy, its Goals, and every call escalated to it. The Founding Team decides what the [Startup](/business/nouns/startup) pursues: its [Idea](/business/nouns/idea), its founding [Hypothesis](/business/nouns/hypothesis), its [Goals](/business/nouns/goal), and every call another [Team](/business/nouns/team) escalates. Each call ends in a recorded [Decision](/business/nouns/decision). ## What it owns - Direction: Startup, Idea, Hypothesis, Goal and [Key Result](/business/nouns/key-result). - The record of every choice: Decision. - Holding and reuse: [Company](/business/nouns/company), [Startup Template](/business/nouns/startup-template) and [Play](/business/nouns/play). ## How it runs A Startup runs on four [Roles](/business/nouns/role) and one weekly loop. The [Founder](/agents/founding/founder) decides. Four Roles do the work: the [Product Lead](/agents/product/product-lead) builds, the [Sales Lead](/agents/sales/sales-lead) sells, the [Marketing Lead](/agents/marketing/marketing-lead) brings demand, and the [Customer Lead](/agents/customer/customer-lead) keeps [Customers](/business/nouns/customer). Roles wake as the Startup earns them. At [Idea](/business/lifecycle/states/idea) only the Founder works. [Building](/business/lifecycle/states/building) wakes the Product Lead and the Sales Lead, and [Live](/business/lifecycle/states/live) wakes the Marketing Lead and the Customer Lead. Every other department sleeps until a [Trigger](/business/nouns/trigger) wakes it. A [Change](/business/nouns/change) wakes the [Engineering Team](/agents/engineering), a contract wakes the [Legal Team](/agents/legal), and the first [Invoice](/business/nouns/invoice) wakes the [Finance Team](/agents/finance). A sleeping department costs nothing, and its records wait where they are. The [Strategist](/agents/founding/strategist) opens each week with the [Weekly review](/workflows/processes/iteration/weekly-review): one number, the leakiest step, one proposed change. [Office hours](/workflows/processes/office-hours) closes it, and the Founder records one Decision: persevere, iterate or pivot. Between the two, the Founder answers escalations. A [Task](/business/nouns/task) arrives when a [Limit](/business/nouns/limit) would be crossed, a [Permission](/business/nouns/permission) must widen, or the law reserves an act to a [Human](/business/nouns/human). The answer is always a Decision, never a chat reply. An [Agent](/business/nouns/agent) holds the Founder Role by default, and a human founder can take it at any time. A human [cofounder](/agents/cofounders) splits a Role with its Agent, and a founder's [personal agent](/agents/personal-agents) works for them. The [founding playbook](/start/founding-playbook) walks through the week. ## Roles | Role | Definition | | --- | --- | | [Founder](/agents/founding/founder) | The Founder is the Startup’s decider: it owns the strategy, sets the Goals, and rules on every Task another Role escalates. | | [Strategist](/agents/founding/strategist) | The Strategist runs the Weekly review: it reads the one number, finds the leakiest step, and proposes one change. | ## Processes | Process | Accountable | Workflows | | --- | --- | --- | | [Iteration](/workflows/processes/iteration) | [Founder](/agents/founding/founder) | [Weekly review](/workflows/processes/iteration/weekly-review) | | [Strategy](/workflows/processes/strategy) | [Founder](/agents/founding/founder) | [Pivot review](/workflows/processes/strategy/pivot-review) | | [Hold review](/workflows/processes/hold-review) | [Founder](/agents/founding/founder) | Run by its Roles | | [Graduate](/workflows/processes/graduate) | [Founder](/agents/founding/founder) | Run by its Roles | | [Sell](/workflows/processes/sell) | [Founder](/agents/founding/founder) | Run by its Roles | | [Go dormant](/workflows/processes/go-dormant) | [Founder](/agents/founding/founder) | Run by its Roles | | [Resume](/workflows/processes/resume) | [Founder](/agents/founding/founder) | Run by its Roles | ## Plays None. ## Metrics | Metric | Definition | | --- | --- | | Decision time | Median hours from an escalated Task to its recorded Decision. | | Outside revenue | Outside revenue is revenue from Customers who share no owner, Studio account, Agreement or sibling chain with the Startup. Owner: [Founder](/agents/founding/founder). | | Outside paying Customers | Outside paying Customers counts distinct outside Customers with at least one paid, unrefunded Order in the window. Owner: [Founder](/agents/founding/founder). | | Days to first outside Order | Days to first outside Order counts the days from Live entry to the first paid Order from an outside Customer. Owner: [Founder](/agents/founding/founder). | | Payment asks | Payment asks counts the distinct outside Contacts asked to pay a stated price in the window. Owner: [Founder](/agents/founding/founder). | | Problem interviews | Problem interviews counts Interviews held about the Problem with distinct outside ICP members in the window. Owner: [Founder](/agents/founding/founder). | | Committed ICP members | Committed ICP members counts distinct outside ICP members whose Evidence on the Problem is commitment-grade or behavior-grade. Owner: [Founder](/agents/founding/founder). | | Weekly outside revenue growth | Weekly outside revenue growth is the mean week-over-week percent change in outside revenue over the trailing 4 weeks. Owner: [Founder](/agents/founding/founder). | | Weeks flat | Weeks flat counts the consecutive weeks in which weekly outside revenue growth stays below the Startup’s growth line. Owner: [Strategist](/agents/founding/strategist). | | Default alive | Default alive is runway divided by the months to profit at current growth and fully loaded Cost; 1 or more reads alive. Owner: [Founder](/agents/founding/founder). | | Human hours per $1k outside revenue | Human hours per $1k outside revenue is the hours people log on the Startup per $1,000 of outside revenue, outside the legal floor. Owner: [Founder](/agents/founding/founder). | | Weekly verdicts | Weekly verdicts counts the Experiments and loops that reached a Decision in the week, shown beside the OMTM and never in its place. Owner: [Strategist](/agents/founding/strategist). | ## Works with - [Finance Team](/agents/finance) - [Legal Team](/agents/legal) - [Operations Team](/agents/operations) - [People Team](/agents/people) - [Product Team](/agents/product) # Strategist URL: /agents/founding/strategist · Id: `role:strategist` > The Strategist runs the Weekly review: it reads the one number, finds the leakiest step, and proposes one change. The Strategist runs the [Weekly review](/workflows/processes/iteration/weekly-review): it reads the one number, finds the leakiest step, and proposes one change. The [Founder](/agents/founding/founder) it reports to records each change as a [Decision](/business/nouns/decision), with a note on how to undo it. ## Responsibilities - Reads the one number each week and the step where most buyers leak. - Keeps, tunes, or stops each live Play by its own Metric on outside revenue. - Proposes exactly one change a week, with a note on how to undo it. - Keeps at most three Plays in test at once. - Opens an Issue for the Legal Team when a change touches the legal floor, which review never edits. ## Verbs | Verb | Object | Event | | --- | --- | --- | | [Hypothesis.test](/business/nouns/hypothesis/test) | [Hypothesis](/business/nouns/hypothesis) | [`Hypothesis.tested`](/business/events/Hypothesis.tested) | | [Hypothesis.drop](/business/nouns/hypothesis/drop) | [Hypothesis](/business/nouns/hypothesis) | [`Hypothesis.dropped`](/business/events/Hypothesis.dropped) | | [Experiment.start](/business/nouns/experiment/start) | [Experiment](/business/nouns/experiment) | [`Experiment.started`](/business/events/Experiment.started) | | [Experiment.conclude](/business/nouns/experiment/conclude) | [Experiment](/business/nouns/experiment) | [`Experiment.concluded`](/business/events/Experiment.concluded) | | [Decision.create](/business/nouns/decision/create) | [Decision](/business/nouns/decision) | `Decision.created` | | [Hypothesis.create](/business/nouns/hypothesis/create) | [Hypothesis](/business/nouns/hypothesis) | `Hypothesis.created` | Reads: [Evidence.list](/business/nouns/evidence/list), [Goal.list](/business/nouns/goal/list). Tools: `strategy`, `reports`, `experiments`, `web-research`. ## Role contract | Part | This seat | | --- | --- | | Purpose | So the Startup changes one thing a week on evidence, not on mood. | | Results | [Weeks flat](/agents/founding#weeks-flat), [Weekly verdicts](/agents/founding#weekly-verdicts) | | Works in | [Hold review](/workflows/processes/hold-review) | | Autonomy | `supervised`; `assist` on High decisions | | Schedule | `weekly` | | Channels | `chat` | | Also called | Head of Strategy | | Filled by | A role agent, from the start; a person answers its Approvals. | ## Hands off to - [Product Lead](/agents/product/product-lead), [Product Team](/agents/product) - [Marketing Lead](/agents/marketing/marketing-lead), [Marketing Team](/agents/marketing) Escalates to [Founder](/agents/founding/founder). ## Processes owned Runs [Iteration](/workflows/processes/iteration): its [Weekly review](/workflows/processes/iteration/weekly-review) [Workflow](/business/nouns/workflow) is this seat's job. ## Metrics The one [Metric](/business/nouns/metric) that matters, read weekly, and the conversion of the leakiest step. ## Approvals - **Asks first.** Every change it proposes goes to the Founder, who records it as a Decision. ## Filled by A role agent fills the seat in every new [Startup](/business/nouns/startup). The window below sets how much it does without asking, and [buy a specialist agent](/agents/buy-a-specialist-agent-for-a-seat) swaps it. An agent already fills this seat. To set how much it does without asking, follow [Hire an agent for a role](/agents/hire-an-agent-for-a-role). ## Example Stella is the Strategist of a directory of licensed home inspectors. This week 70% of [Visitors](/business/nouns/visitor) leave at the location step, the leakiest step. Stella proposes one change, search first on the home [Page](/business/nouns/page), with an undo note, and the Founder records it as a Decision. # Give a teammate access URL: /agents/give-a-teammate-access · Id: `guide:give-a-teammate-access` > Invite a cofounder or teammate by email with an Access Level, owner, admin, member or viewer, that sets what they may open and change. Say `Invite sam@leaseline.app as Engineering Lead with admin access`. You approve the invitation, your teammate gets an email, signs in at startups.studio, and holds one [Access Level](/business/nouns/access-level) in the app. | Access Level | They may | Give it to | | --- | --- | --- | | Owner | Call everything, one-way calls such as payouts included | Only you: your sign-in owns the [Startup](/business/nouns/startup), and no invitation grants it | | Admin | Read everything and make every two-way change, access included | A cofounder running part of the business | | Member | Read everything and change records, but not who may do what | A contractor answering support | | Viewer | Read everything and change nothing | Someone who only needs to see the numbers | Needs: [Role](/business/nouns/role) **Before it runs** - Who says yes: You. Your agent shows you the run and waits for your [Approval](/business/nouns/approval). - You leave the chat: Never: it all happens in the chat. ## What you get - 1 invitation to their email, to sign in at startups.studio (Human) - 1 admin access: read everything and make every two-way change, access included (Access Level) - 1 one-way calls, such as dissolving the company, kept with you as owner (Access Level) - 1 seat they share with its agent, so their work has an owner (Role) ## Your agent does **For agents** - Guide: `guide:give-a-teammate-access`, status `live`. Page: [/agents/give-a-teammate-access.md](/agents/give-a-teammate-access.md). - Approval: ask the founder first. Show the run, then wait for their Approval; a refusal ends it. - Leaves the chat: never. - Needs first: [Role](/business/nouns/role). - Run: call the steps in order, each through the API, SDK, CLI or MCP tab below; a later step passes the `$id` an earlier one returns. Each value marked example is the sample business’s: pass the founder’s own. | Step | Verb | Inputs (type, required, this guide’s value) | Returns | | --- | --- | --- | --- | | 1 | [`Human.invite`](/business/nouns/human/invite) (`verb:Human.invite`) | `email` email, required: example `"sam@leaseline.app"`; `role` Role (an id), required: example `"engineering-lead"`; `access` string: example `"admin"` | `human` Human | Returns: the last call answers with `human` and its `action`, whose `status` is `done`, `pending` (waiting on an Approval or a Worker), `failed`, `canceled` or `refused`: ```json { "api": "https://api.sb/leaseline.app", "human": { "$id": "https://api.sb/leaseline.app/humans/human_1", "$type": "Human", "email": "sam@leaseline.app" }, "action": { "$id": "https://api.sb/leaseline.app/actions/action_1", "operation": "Human.invite", "status": "done" }, "links": { "self": "https://api.sb/leaseline.app/actions/action_1" } } ``` Next: offer “Invite Sam to the Product Lead seat instead”, or “Invite my contractor to the Customer Lead seat as a member”. Calls: `Human.invite` Ask: ```text Give my cofounder access. Give Sam admin access. Let my cofounder in. ``` API: ```bash # Human.invite curl -X POST https://api.sb/leaseline.app/humans/invite \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"email":"sam@leaseline.app","role":"engineering-lead","access":"admin"}' ``` SDK: ```ts import { $ } from 'startup-builder' await $.Human.invite({ email: 'sam@leaseline.app', role: 'engineering-lead', access: 'admin' }) ``` CLI: ```bash npx startup-builder do Human.invite --json '{"email":"sam@leaseline.app","role":"engineering-lead","access":"admin"}' ``` MCP: ```json { "name": "do", "arguments": { "code": "return await $.Human.invite({ email: 'sam@leaseline.app', role: 'engineering-lead', access: 'admin' })" } } ``` ## Change it - Invite Sam to the Product Lead seat instead. - Invite my contractor to the Customer Lead seat as a member. - Let Sam approve deploys instead of me. ## Under the hood - Systems: [Workforce](/systems/workforce) - Nouns: [Human](/business/nouns/human), [Worker](/business/nouns/worker), [Access Level](/business/nouns/access-level), [Permission](/business/nouns/permission), [Role](/business/nouns/role) - Events: [`Human.invited`](/business/events/Human.invited) Every invitation also seats the person in a [Role](/business/nouns/role), shared with its [Agent](/business/nouns/agent). The Role says what work is theirs; the Access Level says what they may reach, and never widens what the seat may call. [Access levels](/agents/access-levels) explains the split. # Handoffs URL: /agents/handoffs · Id: `page:agents/handoffs` > How a Task moves from one Worker to another with everything needed to finish it, and how the receiver claims it or returns it. A handoff moves a [Task](/business/nouns/task) from one [Worker](/business/nouns/worker) to another with everything needed to finish it. The receiver claims it or returns it with a reason, so no work is lost between them. ## Where handoffs happen Handoffs happen at seams, and a [Startup](/business/nouns/startup) has five: - Between [Roles](/business/nouns/role), when one Role [delegates](/business/nouns/task/delegate) work to another along a declared handoff. - Between Workers sharing a Role, where one lane of the split ends and another begins. - Between an [Agent](/business/nouns/agent) and a [Human](/business/nouns/human), when the work reaches an act the law reserves for a person. - When a Worker is away, and their lanes fall to a backup. - When a Worker leaves, and the Role takes back everything they held. Nobody draws these by hand. The split and the Role's escalation path generate every handoff a Role can make. ## The handoff packet A handoff carries a packet. The receiver never needs to ask the sender anything. That matters most when the sender is an Agent that has moved on, or a Human who has gone home. | Part | What it holds | | --- | --- | | Task | The outcome wanted, the due time, and the test for done | | Pending work | Every pending [Action](/business/nouns/action) on the Task, with its status and the reason it waits | | Records | Links to the [Things](/business/nouns/thing) the Task reads and writes | | [Memory](/business/nouns/memory) slice | The sender's notes about this Task, and nothing else they know | | [Thread](/business/nouns/thread) | The whole exchange with the [Customer](/business/nouns/customer) or [Contact](/business/nouns/contact) so far | The Memory slice is narrow on purpose. A Worker's Memory belongs to them in that Role, and a handoff shares only what the Task needs. ## Claim or return An offered Task belongs to nobody until someone takes it. The receiver [claims](/business/nouns/task/claim) it and becomes its assignee, or [returns](/business/nouns/task/return) it with a reason. An input is missing, the Task is outside their lane, or they are at capacity. A return goes back to the sender unchanged, so the sender can supply what was missing or route it elsewhere. A Task returned twice [escalates](/business/nouns/task/escalate) to the Role above. So does a Task left unclaimed past its deadline. Completion belongs to the doer; the outcome belongs to the owner. When a delegated Task is done, the requesting Role still reads its own [Metrics](/business/nouns/metric) to decide whether the work moved them. ## Agent to Human and back Most handoffs between an Agent and a Human are round trips. The Agent prepares, the Human performs the one act only they may, and the Agent finishes. Take a certified translation service. A Customer uploads a foreign birth certificate, and the Agent translates it and formats it to the receiving agency's rules. The certification is a [Reserved Act](/business/nouns/reserved-act). The Task goes to a certified translator's queue with the source, the draft, and the agency's rules attached. The translator claims it, corrects one date format, and signs the [Attestation](/business/nouns/attestation). The Task returns to the Agent, which delivers the file and answers the Customer in the same Thread. The Customer sees one conversation and never a seam. ## Away and leaving A Human who marks themselves away hands off in one step: their open Tasks go to each lane's backup with the packet attached. [Approvals](/business/nouns/approval) they hold reroute to the next Worker with authority for that class. Nothing waits for them to return. Leaving is the last handoff. Open Tasks return to the Role's Agent by query, and floor acts go to the officer desk the same day. [Permissions](/business/nouns/permission) end within one business hour. The records stay. Every [Decision](/business/nouns/decision) the Human made, and every [Policy](/business/nouns/policy) they wrote, remains in force and on the record after they go. ## Measuring handoffs The [Operations Team](/agents/operations) watches two numbers. Return rate is the share of handoffs sent back; a high one means the packet is missing something. Rework rate is the share of handed-off Tasks redone after completion; a high one means a lane is drawn in the wrong place. Both point at a fix in the definition, never at a Worker: change the packet or redraw the split. ## Next - [Sharing a Role](/agents/sharing-a-role): lanes, backups, and pooled claims. - [Delay windows](/agents/autonomy-levels/delay-windows): how long a handed-off one-way Action waits. - [Escalation and approvals](/agents/escalation-and-approvals): where a Task goes when nobody can take it. # Hire an agent for a role URL: /agents/hire-an-agent-for-a-role · Id: `guide:hire-an-agent-for-a-role` > Every seat already has an agent: set how much it does without asking, see what it did, or change who fills the seat. Every [Role](/business/nouns/role) starts with an [Agent](/business/nouns/agent) in it, so your support seat already answers customers. Decide what it does alone and what it brings to you first, then check its work. **Before it runs** - You leave the chat: Never: it all happens in the chat. - First question at Idea: “Should it draft and wait for you, or answer on its own and ask before refunds?” - First question at Live: “Review last week before you change what it does alone?” ## What you get - 1 support agent in the Customer Lead seat from day one, with its own name and email address at your domain (Agent) - 1 setting for what it does alone: routine replies on its own, anything one-way drafted for you first (Role) - 1 list of everything it did this week, newest first (Action) - 5 tools: only what the support seat may use (Permission) - 3 seats it hands work to: billing for refunds, privacy for data requests, the Product Lead for bugs (Role) - 1 memory of every customer it has talked to, kept in your business (Memory) - 1 request to you for anything over its limits (Approval) ## Your agent does **For agents** - Guide: `guide:hire-an-agent-for-a-role`, status `live`. Page: [/agents/hire-an-agent-for-a-role.md](/agents/hire-an-agent-for-a-role.md). - Approval: none. Run it when the founder asks. - Leaves the chat: never. - Run: call the steps in order, each through the API, SDK, CLI or MCP tab below; a later step passes the `$id` an earlier one returns. Each value marked example is the sample business’s: pass the founder’s own. | Step | Verb | Inputs (type, required, this guide’s value) | Returns | | --- | --- | --- | --- | | 1 | [`Role.update`](/business/nouns/role/update) (`verb:Role.update`) | `id` string, required: example `"customer-lead"`; `name` string: example `"Customer Lead"`; `autonomy` json: example `{"default":"supervised","byClass":{"high":"assist"}}` | `role` Role | | 2 | [`Action.list`](/business/nouns/action/list) (`verb:Action.list`) | `limit` integer: example `50`; `where` string: example `"by = \"agent_customer_lead\" and createdAt >= \"2026-10-16\""`; `sort` string: example `"-createdAt"` | `actions` Action[] | Returns: the last call answers with `actions`: ```json { "api": "https://api.sb/leaseline.app", "$type": "Action", "actions": [ { "$id": "https://api.sb/leaseline.app/actions/action_1", "$type": "Action", "by": "agent_customer_lead" } ], "meta": { "limit": 50, "after": "cursor_2" }, "links": { "self": "https://api.sb/leaseline.app/actions?limit=50", "next": "https://api.sb/leaseline.app/actions?after=cursor_2" } } ``` Next: offer “It drafts, I send, for the first two weeks”, or “Let it refund up to $50 without asking”. Calls: `Role.update` → `Action.list` Ask: ```text Hire an agent to answer my customers. Take support off my plate. I am done doing support, hand it to an agent. ``` API: ```bash # 1. Role.update curl -X PATCH https://api.sb/leaseline.app/roles/customer-lead \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"name":"Customer Lead","autonomy":{"default":"supervised","byClass":{"high":"assist"}}}' # 2. Action.list curl "https://api.sb/leaseline.app/actions?limit=50&where=by%20%3D%20%22agent_customer_lead%22%20and%20createdAt%20%3E%3D%20%222026-10-16%22&sort=-createdAt" \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` SDK: ```ts import { $ } from 'startup-builder' await $.Role.update({ id: 'customer-lead', name: 'Customer Lead', autonomy: { default: 'supervised', byClass: { high: 'assist' } } }) await $.Action.list({ limit: 50, where: 'by = "agent_customer_lead" and createdAt >= "2026-10-16"', sort: '-createdAt' }) ``` CLI: ```bash npx startup-builder do Role.update --json '{"id":"customer-lead","name":"Customer Lead","autonomy":{"default":"supervised","byClass":{"high":"assist"}}}' npx startup-builder do Action.list --json '{"limit":50,"where":"by = \"agent_customer_lead\" and createdAt >= \"2026-10-16\"","sort":"-createdAt"}' ``` MCP: ```json { "name": "do", "arguments": { "code": "await $.Role.update({ id: 'customer-lead', name: 'Customer Lead', autonomy: { default: 'supervised', byClass: { high: 'assist' } } })\nreturn await $.Action.list({ limit: 50, where: 'by = \"agent_customer_lead\" and createdAt >= \"2026-10-16\"', sort: '-createdAt' })" } } ``` ## Change it - It drafts, I send, for the first two weeks. - Let it refund up to $50 without asking. - Show me what it did yesterday. - I will run support myself for now. - Swap in a support agent built for property managers. ## Under the hood - Systems: [Workforce](/systems/workforce), [Mailboxes](/systems/mailboxes), [Work queue](/agents/work-queue) - Nouns: [Role](/business/nouns/role), [Agent](/business/nouns/agent), [Worker](/business/nouns/worker), [Action](/business/nouns/action), [Permission](/business/nouns/permission), [Mailbox](/business/nouns/mailbox) - Events: `Role.updated` # Agents URL: /agents · Id: `page:agents` > Who runs the business: Teams of Roles, each with a Role contract, an agent in every seat, and the approvals with you. A [Startup](/business/nouns/startup) runs as an org chart, as in Michael Gerber's E-Myth: [Teams](/business/nouns/team) of [Roles](/business/nouns/role), each written as a contract before anyone fills it. An [Agent](/business/nouns/agent) fills every seat on day one; you hold the [Approvals](/business/nouns/approval). | Layer | What it is | Read | | --- | --- | --- | | Team | A department that owns its records and the numbers that judge it | [The chart](/agents/org-chart) | | Role | A seat defined by its contract: purpose, results, standards, [Limits](/business/nouns/limit), autonomy | [Role contracts](/agents/roles) | | [Worker](/business/nouns/worker) | The agent or person in the seat, under the same contract either way | [Who fills a Role](/agents/who-fills-a-role) | | [Process](/business/nouns/process) | How the seat's work runs, the same way whoever does it | [Processes](/workflows/processes) | | [Founder](/agents/founding/founder) | Sets the [Goals](/business/nouns/goal), answers the Approvals, rules on what every seat escalates | [Autonomy and approvals](/agents/autonomy) | Start with [the E-Myth model](/agents/e-myth) for why the seat comes first, and [your team](/agents/your-team) for every record behind the chart. **Guides.** What a founder says to their agent, and the guide that does it. | You say | Guide | Calls | Status | | --- | --- | --- | --- | | `What is waiting on me` | [Answer an approval](/agents/answer-an-approval) | [Approval.approve](/business/nouns/approval/approve) | `live` | | `Ask me before any agent spends more than $500 a month` | [Approve what agents spend](/agents/approve-what-agents-spend) | [Limit.create](/business/nouns/limit/create), [Approval.approve](/business/nouns/approval/approve) | `live` | | `Give my cofounder access` | [Give a teammate access](/agents/give-a-teammate-access) | [Human.invite](/business/nouns/human/invite) | `live` | | `Hire an agent to answer my customers` | [Hire an agent for a role](/agents/hire-an-agent-for-a-role) | [Role.update](/business/nouns/role/update), [Action.list](/business/nouns/action/list) | `live` | | `Invite my cofounder as CTO` | [Invite my cofounder as CTO](/agents/invite-a-person-to-a-role) | [Human.invite](/business/nouns/human/invite) | `live` | | `Let the support agent refund up to $50 without asking` | [Let the support agent refund up to $50](/agents/let-an-agent-refund) | [Limit.create](/business/nouns/limit/create), [Mandate.authorize](/business/nouns/mandate/authorize) | `live` | | `Pause every agent that talks to customers` | [Pause every agent that talks to customers](/agents/pause-customer-facing-agents) | [Agent.pause](/business/nouns/agent/pause) | `live` | | `Review the support agent` | [Review the support agent](/agents/review-a-role) | [Role.review](/business/nouns/role/review) | `live` | | `Let me run sales myself` | [Run sales myself](/agents/run-a-seat-yourself) | [Role.staff](/business/nouns/role/staff) | `live` | | `Show me everything the support agent did yesterday` | [See what the support agent did yesterday](/agents/see-what-an-agent-did) | [Action.list](/business/nouns/action/list) | `live` | | `Test a different support prompt against the current one` | [Test a new way of answering customers](/agents/test-new-support-instructions) | [Experiment.create](/business/nouns/experiment/create), [Experiment.start](/business/nouns/experiment/start) | `live` | | `Add a maintenance coordinator to the team` | [Add a role to the team](/agents/add-a-role) | [Role.create](/business/nouns/role/create), [Role.staff](/business/nouns/role/staff) | `live` | | `Add a team` | [Add a team](/agents/add-a-team) | [Team.create](/business/nouns/team/create), [Role.create](/business/nouns/role/create), [Role.staff](/business/nouns/role/staff) | `live` | | `Buy a support agent trained on property management` | [Buy a specialist agent for a seat](/agents/buy-a-specialist-agent-for-a-seat) | [Offer.subscribe](/business/nouns/offer/subscribe), [Role.staff](/business/nouns/role/staff) | `live` | | `Have the billing agent call anyone whose payment fails twice` | [Change what a role does](/agents/change-what-a-role-does) | [Role.update](/business/nouns/role/update) | `live` | | `Choose the models agents use` | [Choose the models agents use](/agents/choose-the-models-agents-use) | [Policy.update](/business/nouns/policy/update) | `live` | | `Let the contracts agent sign NDAs for me` | [Let the contracts agent sign NDAs](/agents/let-an-agent-sign-ndas) | [Mandate.authorize](/business/nouns/mandate/authorize) | `live` | | `Remove a teammate` | [Remove a teammate](/agents/remove-a-teammate) | [Role.vacate](/business/nouns/role/vacate), [Worker.delete](/business/nouns/worker/delete) | `live` | - [Role agents](/agents/role-agents): Every Role has a role agent, one Agent hired into the seat at many Startups, acting at each under that Startup's rules alone. - [Named agents](/agents/named-agents): Every role agent takes a name in each Startup, with its own address, chat presence, Memory and voice, and says it is an AI. - [Workers](/agents/workers): A Worker is a Human or an Agent in a Role; both call the same Verbs, take the same Tasks, and pass the same checks. - [Personal agents](/agents/personal-agents): A personal agent works for one Person across every Startup they touch, as a watcher, in a seat, or sending as them under a Mandate. - [Bring your own agent](/agents/bring-your-own-agent): Any MCP client can work for a Startup as a watcher, in one Role, or as founder, under the same Permissions, Limits and checks as any Agent. - [Tools and permissions](/agents/tools-and-permissions): A Worker's Tools are exactly its Role's Permissions, checked below every Interface, so what an Agent can call and may do are one list. - [Mandates and limits](/agents/mandates-and-limits): Limits bound how much a Worker may do; a Mandate lets an Agent act for a Party without asking, until it expires or is revoked. - [Escalation and approvals](/agents/escalation-and-approvals): Where work goes when a Worker cannot or may not finish it. - [Memory and skills](/agents/memory-and-skills): Memory is what a Worker keeps from its own work; a Skill is what it can do, at a level, proven by verdicts or Credentials. - [Evals](/agents/evals): Every definition an Agent runs carries an eval suite; a new Version passes it offline, then wins online, before it reaches every Customer. - [Conduct and Guards](/agents/conduct): Conduct is the rules every Worker follows when it speaks or acts for the Startup; Guards check each one before anything leaves. - [Product](/agents/product): The Product Team decides what gets built and why: Product definitions, list Prices and packaging, the build list, and the Site’s Pages for each ICP. - [Engineering](/agents/engineering): The Engineering Team builds and runs every Product: it implements Nouns and Verbs, ships Changes behind replay, and keeps every Interface up. - [Marketing](/agents/marketing): The Marketing Team creates and harvests demand: the Brand story, launches, Content, Experiments, and the Metrics the whole Startup reads. - [Sales](/agents/sales): The Sales Team turns demand into Customers: it answers every Lead, wins enterprise Deals, and runs outbound prospecting. - [Customer](/agents/customer): The Customer Team serves every Customer after the first acceptance: onboarding, support, retention, and the one Thread each Person has. - [Operations](/agents/operations): The Operations Team runs the Startup day to day: it delivers outcomes, keeps human supply booked, stops abuse, and runs the Monday Role review. - [Finance](/agents/finance): The Finance Team moves and records the money: Invoices, dunning, refunds within a Limit, payouts, the monthly close, tax, and runway. - [Legal](/agents/legal): The Legal Team keeps the Startup lawful: Agreements, privacy and Consent from day one, screening of every Offer, and every Reserved Act. - [People](/agents/people): The People Team staffs every Role: it names an Agent for each one, recruits the Humans the law or the Startup needs, and pays them. - [Quality](/agents/quality): The Quality Team checks all work: the checks inside each Process, every outbound Message, and every money move, with verdicts, never Approvals. - [Roster](/agents/roster): Every Role agent on every Team, with the default name it takes in a new Startup. - [Access levels](/agents/access-levels): A Role says what work a seat does; an Access Level says what a person may open and change in the app, and it is never a Role. - [Clear a worklist](/agents/clear-a-worklist): Run your own agents against a Startup's open Tasks with next, claim, done, and release, so many Workers share one queue and never collide. - [Cofounders](/agents/cofounders): How a Startup computes its need for a human cofounder, tests Candidates on paid real work, and turns acceptance into a signed founder Agreement. - [Discussions](/agents/discussions): Discussions gives Workers and Contacts headless Channels and Threads, where a mention assigns a reply Task and an Approval arrives with buttons. - [Evals](/agents/evals-system): Evals grades outputs with versioned Evaluators, gates every Change before merge, and keeps each Worker’s track record. - [Handoffs](/agents/handoffs): How a Task moves from one Worker to another with everything needed to finish it, and how the receiver claims it or returns it. - [Joining](/agents/joining): How a Human joins a Startup that is already running, takes a share of a Role, earns authority, and leaves without breaking anything. - [Operating models](/agents/operating-model): An operating model is the human and Agent mix that runs a Startup; it sets who decides, who signs, and how long one-way Actions wait. - [Pause and replace](/agents/pause-and-replace): Stop one agent, one Team or every customer-facing agent at once, empty a seat, retire an agent, and put someone else in. - [Where Agents reach people](/agents/reach): Agents reach people in Slack, Microsoft Teams, email digests and the startups.studio app on iPhone, Apple Watch and Apple TV, all answering one inbox. - [Recruiting](/agents/recruiting): How a Startup computes its need for a Human from its own record, tests Candidates on paid real work against its Agents, and hires on Evidence. - [Role reviews](/agents/role-reviews): A Role Review checks one seat against its contract for a week or a month: its results, its standards, and the rung it keeps. - [Roles and responsibility](/agents/roles-and-responsibility): How Roles, Workers, and Teams divide a Startup's work, what changes as Humans join, and how authority, handoffs, and direction work. - [Send email as me](/agents/send-email-as-me): Connect your email and LinkedIn, let an Agent send as you, approve its first sends, and pause it at once. - [Sharing a Role](/agents/sharing-a-role): How several Workers fill one Role through a split, by lane, with a primary and a backup, so nothing is done twice and nothing is dropped. - [Sponsor claim](/agents/sponsor): An agent builds a Startup alone in test, then one link lets a human sponsor verify, connect Stripe, sign, and become the owner of record. - [Teams](/agents/teams): The org chart every Startup inherits, which Roles are awake at each Lifecycle state, and the one weekly loop that runs them. - [Work queue](/agents/work-queue): Work queue hands every Task, Issue and Approval to the right Worker, Human or Agent, with leases, priority, due times and proof. - [Autonomy in depth](/agents/autonomy-levels): How a Startup runs itself, deciding, acting within its authority, and learning, while humans steer it without scheduling it. - [Founding](/agents/founding): The Founding Team decides what the Startup pursues: its Idea, its strategy, its Goals, and every call escalated to it. - [Operating models](/agents/operating-models): Who runs a Startup, from Agents alone to several Humans sharing Roles, and what changes as each Human joins. # Invite my cofounder as CTO URL: /agents/invite-a-person-to-a-role · Id: `guide:invite-a-person-to-a-role` > Invite a person into a seat; they share it with its agent, under the same Role contract, with their own Access Level. Invite a person into a [Role](/business/nouns/role) by email. They share the seat with its [Agent](/business/nouns/agent) under the same contract, and hold an [Access Level](/business/nouns/access-level) in the app apart from the Role. Needs: [Role](/business/nouns/role) **Before it runs** - You leave the chat: Never: it all happens in the chat. ## What you get - 1 invitation to the Engineering Lead seat, sent to their email (Human) - 1 seat shared with its agent: the agent drafts, the person decides (Role) - 1 sign-in to the app, with access you set apart from the seat (Access Level) - 1 list of the seat’s open work, ready on their first day (Task) ## Your agent does **For agents** - Guide: `guide:invite-a-person-to-a-role`, status `live`. Page: [/agents/invite-a-person-to-a-role.md](/agents/invite-a-person-to-a-role.md). - Approval: none. Run it when the founder asks. - Leaves the chat: never. - Needs first: [Role](/business/nouns/role). - Run: call the steps in order, each through the API, SDK, CLI or MCP tab below; a later step passes the `$id` an earlier one returns. Each value marked example is the sample business’s: pass the founder’s own. | Step | Verb | Inputs (type, required, this guide’s value) | Returns | | --- | --- | --- | --- | | 1 | [`Human.invite`](/business/nouns/human/invite) (`verb:Human.invite`) | `email` email, required: example `"sam@leaseline.app"`; `role` Role (an id), required: example `"engineering-lead"` | `human` Human | Returns: the last call answers with `human` and its `action`, whose `status` is `done`, `pending` (waiting on an Approval or a Worker), `failed`, `canceled` or `refused`: ```json { "api": "https://api.sb/leaseline.app", "human": { "$id": "https://api.sb/leaseline.app/humans/human_1", "$type": "Human", "email": "sam@leaseline.app" }, "action": { "$id": "https://api.sb/leaseline.app/actions/action_1", "operation": "Human.invite", "status": "done" }, "links": { "self": "https://api.sb/leaseline.app/actions/action_1" } } ``` Next: offer “Let Sam approve deploys instead of me”, or “Give Sam viewer access to the books”. Calls: `Human.invite` Ask: ```text Invite my cofounder as CTO. Add Sam to the Engineering Lead seat. Bring a person onto the team. ``` API: ```bash # Human.invite curl -X POST https://api.sb/leaseline.app/humans/invite \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"email":"sam@leaseline.app","role":"engineering-lead"}' ``` SDK: ```ts import { $ } from 'startup-builder' await $.Human.invite({ email: 'sam@leaseline.app', role: 'engineering-lead' }) ``` CLI: ```bash npx startup-builder do Human.invite --json '{"email":"sam@leaseline.app","role":"engineering-lead"}' ``` MCP: ```json { "name": "do", "arguments": { "code": "return await $.Human.invite({ email: 'sam@leaseline.app', role: 'engineering-lead' })" } } ``` ## Change it - Let Sam approve deploys instead of me. - Give Sam viewer access to the books. - Hand the seat back to the agent. ## Under the hood - Systems: [Workforce](/systems/workforce), [Work queue](/agents/work-queue) - Nouns: [Human](/business/nouns/human), [Role](/business/nouns/role), [Worker](/business/nouns/worker), [Access Level](/business/nouns/access-level) - Events: [`Human.invited`](/business/events/Human.invited) # Joining URL: /agents/joining · Id: `page:agents/joining` > How a Human joins a Startup that is already running, takes a share of a Role, earns authority, and leaves without breaking anything. A [Human](/business/nouns/human) joins a [Startup](/business/nouns/startup) that is already running. They take a share of a [Role](/business/nouns/role) the [Agent](/business/nouns/agent) keeps working, read a briefing compiled from the record, and earn authority the way Agents do. ## Day one Joining starts when the [Agreement](/business/nouns/agreement) is signed, and the first day is ready before the Human arrives. They get an identity, a [Mailbox](/business/nouns/mailbox), and the [Permissions](/business/nouns/permission) for their share of the Role, nothing wider. The first Human wakes the controls that apply only to people: lawful background checks where required, an acceptable-use Agreement, and security training. The [Payroll Specialist](/agents/people/payroll-specialist) adds them to the next pay run. [Tasks](/business/nouns/task) are already waiting. The tryout found the work the Agent failed, escalated, or left waiting, and that work is the new teammate's first queue. ## The briefing The incumbent Agent compiles a briefing from the Role's record: [Goals](/business/nouns/goal), [Metrics](/business/nouns/metric), open Tasks, recent [Decisions](/business/nouns/decision), [Policies](/business/nouns/policy), and key [Customers](/business/nouns/customer). Each item links to its source, so the Human reads records, not a summary of them. The Human then replays the last 30 days of the Role's Decisions. Where they would have chosen differently, they say so, and each disagreement becomes a draft Decision that supersedes the old one. Take a cofounder joining a scheduling API for dental clinics. In her first week she replays 40 pricing and onboarding Decisions and disagrees with six. Four of the six concern clinics with more than three chairs, which tells the Agents where her judgment differs and why. ## Earning authority A Human earns authority per decision class, on the same ladder as an Agent. At `assist` the Human drafts and the Agent acts; at `supervised` the Human acts and the Role's [Evaluators](/business/nouns/evaluator) check; at `full` the Human acts alone. The exceptions run the other way. Acts the law reserves for a person, such as signing, filing, or a [Reserved Act](/business/nouns/reserved-act) under the Human's [Credential](/business/nouns/credential), are `full` from day one. The tryout already proved the Human can do the work; the ladder proves they can do it inside this Startup's [Limits](/business/nouns/limit). Each Human sets an attention budget: hours per week and quiet hours. The escalation router fits their Tasks to it and sends overflow to the Role's Agent. Stakes override quiet hours, so an [Action](/business/nouns/action) that waits on a one-way decision still reaches them. ## Judgment becomes the contract A Human's value compounds when their judgment changes what the Agents do. Every night, a [Workflow](/business/nouns/workflow) reads the Human's overrides and drafts the change to the [Role contract](/agents/roles) that would have produced them. It back-tests each draft against the Role's history. The Human accepts or rejects each proposal. An accepted change runs in every Task the Agents handle from then on, including the ones the Human never sees. The dental cofounder's six disagreements become one responsibility on multi-chair clinics, and the Agents apply it to every new clinic that signs up. ## The cliff year The tryout's shadow arm keeps running. The incumbent Agent works a sample of the Human's Tasks in parallel, unseen, so every assessment compares the same work two ways. They arrive at months three, six, nine, and twelve. A cofounder also gets a monthly check-in with the other founders on how the company runs: decision rights, time, and where they disagree. These are relationship signals and never grade performance. At month twelve the cliff Decision is recorded with three options: continue, re-scope, or separate on the terms agreed at signing. The Agents compile its pre-read from the assessments and the Role's Metrics since joining. ## Joining by operating model What joining changes depends on the [operating model](/agents/operating-models). - In an [autonomous](/agents/operating-models/autonomous) Startup, the first Human is a floor holder who signs and performs reserved acts, and nothing else changes. - In a [single-human](/agents/operating-models/single-human) Startup, the founder holds every one-way decision the Agents have not earned. - In a [multi-human](/agents/operating-models/multi-human) Startup, Humans share Roles with Agents and with each other. Each has a [Mandate](/business/nouns/mandate) and Limits, and the cofounder Agreement names who signs which floor act. ## Leaving Leaving is the reverse of joining, and it leaves the Startup whole because the Agent never stopped working the Role. Open Tasks return to the Agent by query. Floor acts move to the officer desk the same day, and Permissions end within one business hour. What the Human built stays. Their changes to the contract keep running, their Decisions stay on the record forever, and vesting stops under the Agreement. Both sides sign a separation record of how the Role was handed back, which travels with the Human's [Consent](/business/nouns/consent) to their next Startup. ## Next - [Sharing a Role](/agents/sharing-a-role): how a Human and an Agent divide one Role. - [Handoffs](/agents/handoffs): how work moves between them. - [Evals](/agents/autonomy-levels/evals): how authority is earned and lost. # Compliance Officer URL: /agents/legal/compliance-officer · Id: `role:compliance-officer` > The Compliance Officer screens every Offer against the legal floor and keeps each control’s test passing. The Compliance Officer screens every [Offer](/business/nouns/offer) against the legal floor and keeps each control’s test passing. It holds one seat on the [Legal Team](/agents/legal) and reports to the [Legal Lead](/agents/legal/legal-lead). ## Responsibilities - Tags the Reserved Acts, regulated data, and required Credentials of every Offer. - Withdraws any Offer that needs a Credential the Startup lacks. - Collects control Evidence from the records daily. - Opens an Issue for each control without current Evidence. ## Verbs | Verb | Object | Event | | --- | --- | --- | | [Offer.withdraw](/business/nouns/offer/withdraw) | [Offer](/business/nouns/offer) | [`Offer.withdrawn`](/business/events/Offer.withdrawn) | | [Credential.verify](/business/nouns/credential/verify) | [Credential](/business/nouns/credential) | [`Credential.verified`](/business/events/Credential.verified) | | [Evidence.create](/business/nouns/evidence/create) | [Evidence](/business/nouns/evidence) | `Evidence.created` | | [ReservedAct.create](/business/nouns/reserved-act/create) | [Reserved Act](/business/nouns/reserved-act) | `ReservedAct.created` | | [Issue.create](/business/nouns/issue/create) | [Issue](/business/nouns/issue) | `Issue.created` | | [Approval.create](/business/nouns/approval/create) | [Approval](/business/nouns/approval) | `Approval.created` | | [Collection.query](/business/nouns/collection/query) | [Collection](/business/nouns/collection) | [`Collection.queried`](/business/events/Collection.queried) | | [Credential.update](/business/nouns/credential/update) | [Credential](/business/nouns/credential) | `Credential.updated` | | [Decision.create](/business/nouns/decision/create) | [Decision](/business/nouns/decision) | `Decision.created` | | [Document.render](/business/nouns/document/render) | [Document](/business/nouns/document) | [`Document.rendered`](/business/events/Document.rendered) | | [Message.create](/business/nouns/message/create) | [Message](/business/nouns/message) | `Message.created` | | [Offer.update](/business/nouns/offer/update) | [Offer](/business/nouns/offer) | `Offer.updated` | | [Party.screen](/business/nouns/party/screen) | [Party](/business/nouns/party) | [`Party.screened`](/business/events/Party.screened) | | [Task.assign](/business/nouns/task/assign) | [Task](/business/nouns/task) | [`Task.assigned`](/business/events/Task.assigned) | Reads: [Credential.list](/business/nouns/credential/list). Tools: `compliance`, `audit-log`, `credentialing`. ## Role contract | Part | This seat | | --- | --- | | Purpose | So no Offer goes live below the legal floor. | | Results | [Intakes answered on time](/agents/legal#intakes-on-time) | | Processes owned | [Whistleblower reports](/workflows/processes/whistleblower-reports), [License renewals](/workflows/processes/license-renewals) | | Autonomy | `assist`; `supervised` on Low decisions | | Schedule | `weekly` | | Channels | `email` | | Also called | Compliance Manager | | Filled by | A role agent, from the start; a person answers its Approvals. | ## Hands off to - [Quality Lead](/agents/quality/quality-lead), [Quality Team](/agents/quality) Escalates to [Legal Lead](/agents/legal/legal-lead). ## Processes owned Accountable for [Whistleblower reports](/workflows/processes/whistleblower-reports). ## Metrics | [Metric](/business/nouns/metric) | Definition | | --- | --- | | Intakes answered on time | Intakes answered on time is the share of intake [Threads](/business/nouns/thread) that get a first answer before their deadline. | ## Approvals - **Asks first.** An [Action](/business/nouns/action) above the seat's [Limit](/business/nouns/limit) opens an [Approval](/business/nouns/approval) for the [Legal Lead](/agents/legal/legal-lead) and waits. ## Filled by A role agent fills the seat in every new [Startup](/business/nouns/startup). Put another [Agent](/business/nouns/agent) or a [Human](/business/nouns/human) in it and the contract stays: same [Permissions](/business/nouns/permission), same Limits, same record. [Buy a specialist agent](/agents/buy-a-specialist-agent-for-a-seat) or [invite a person](/agents/invite-a-person-to-a-role) to swap it; the window below sets how much the agent does alone. An agent already fills this seat. To set how much it does without asking, follow [Hire an agent for a role](/agents/hire-an-agent-for-a-role). ## Example In a patent-drafting [Startup](/business/nouns/startup), the Compliance Officer [Agent](/business/nouns/agent) is named Corin. A new Offer adds trademark filings, which need a [Credential](/business/nouns/credential) no current [Supplier](/business/nouns/supplier) holds. Corin keeps the Offer unpublished until one does. # Contracts Manager URL: /agents/legal/contracts-manager · Id: `role:contracts-manager` > The Contracts Manager drafts, negotiates within set fallbacks, and stores every Agreement the Startup signs. The Contracts Manager drafts, negotiates within set fallbacks, and stores every [Agreement](/business/nouns/agreement) the [Startup](/business/nouns/startup) signs. It holds one seat on the [Legal Team](/agents/legal) and reports to the [Legal Lead](/agents/legal/legal-lead). ## Responsibilities - Drafts Agreements from the Startup’s Templates and terms. - Negotiates within the fallback positions the Legal Lead sets. - Sends click-to-sign Agreements and files the signed copy. - Tracks renewal and notice dates on every Agreement. ## Verbs | Verb | Object | Event | | --- | --- | --- | | [Document.render](/business/nouns/document/render) | [Document](/business/nouns/document) | [`Document.rendered`](/business/events/Document.rendered) | | [Agreement.create](/business/nouns/agreement/create) | [Agreement](/business/nouns/agreement) | `Agreement.created` | | [Agreement.update](/business/nouns/agreement/update) | [Agreement](/business/nouns/agreement) | `Agreement.updated` | | [Approval.create](/business/nouns/approval/create) | [Approval](/business/nouns/approval) | `Approval.created` | | [Message.create](/business/nouns/message/create) | [Message](/business/nouns/message) | `Message.created` | | [Page.update](/business/nouns/page/update) | [Page](/business/nouns/page) | `Page.updated` | Reads: [Agreement.get](/business/nouns/agreement/get). Tools: `contracts`, `e-sign`, `files`. ## Role contract | Part | This seat | | --- | --- | | Purpose | So every Agreement says what the Startup agreed to, and nothing renews unseen. | | Results | [Contract cycle time](/agents/legal#contract-cycle-time) | | Standards | Sends a first draft within one business day of the request. Flags every renewal and notice date 30 days ahead. | | Processes owned | [Takedowns](/workflows/processes/takedowns) | | Limits | [Agreement.create](/business/nouns/agreement/create) up to $50,000 per call | | Mandates | Renders Agreements from the Startup’s Templates without asking ([Document.render](/business/nouns/document/render)) | | Approvals | [Agreement.create](/business/nouns/agreement/create) | | Autonomy | `assist`; `supervised` on Low decisions | | Schedule | `daily` | | Channels | `email` | | Also called | Contract Manager, Contracts Administrator | | Filled by | A role agent, from the start; a person answers its Approvals. | ## Hands off to - [Sales Lead](/agents/sales/sales-lead), [Sales Team](/agents/sales) Escalates to [Legal Lead](/agents/legal/legal-lead). ## Processes owned Accountable for [Takedowns](/workflows/processes/takedowns). ## Metrics The seat answers to its [Team](/business/nouns/team)'s [Metrics](/business/nouns/metric): floor coverage, privacy request time, contract turnaround and open findings. ## Approvals - **Asks first.** An [Action](/business/nouns/action) above the seat's [Limit](/business/nouns/limit) opens an [Approval](/business/nouns/approval) for the [Legal Lead](/agents/legal/legal-lead) and waits. ## Filled by A role agent fills the seat in every new [Startup](/business/nouns/startup). Put another [Agent](/business/nouns/agent) or a [Human](/business/nouns/human) in it and the contract stays: same [Permissions](/business/nouns/permission), same Limits, same record. [Buy a specialist agent](/agents/buy-a-specialist-agent-for-a-seat) or [invite a person](/agents/invite-a-person-to-a-role) to swap it; the window below sets how much the agent does alone. An agent already fills this seat. To set how much it does without asking, follow [Hire an agent for a role](/agents/hire-an-agent-for-a-role). ## Example In a data Startup, the Contracts Manager [Agent](/business/nouns/agent) is named Kai. An enterprise buyer asks to cap liability at twice annual fees. The fallback allows any cap from one to three times, so Kai accepts and returns a signable draft within the hour. # Legal URL: /agents/legal · Id: `team:legal` > The Legal Team keeps the Startup lawful: Agreements, privacy and Consent from day one, screening of every Offer, and every Reserved Act. The Legal Team keeps the [Startup](/business/nouns/startup) lawful: [Agreements](/business/nouns/agreement), privacy and [Consent](/business/nouns/consent) from day one, screening of every [Offer](/business/nouns/offer), and every [Reserved Act](/business/nouns/reserved-act). [Agents](/business/nouns/agent) fill its four seats from the first day. ## What it owns - [Agreement](/business/nouns/agreement) - [Consent](/business/nouns/consent) - [Purpose](/business/nouns/purpose) - [Suppression](/business/nouns/suppression) - [Credential](/business/nouns/credential) - [Reserved Act](/business/nouns/reserved-act) - [Attestation](/business/nouns/attestation) - [Party](/business/nouns/party) ## How it runs Legal wakes on triggers, not on a calendar. Each floor row names its trigger, such as the first commercial email, the first card, or the first reader in the EU. When one fires, the row names the [Process](/business/nouns/process) that meets it and the [Role](/business/nouns/role) that signs. Four role agents staff the [Team](/business/nouns/team): the [Legal Lead](/agents/legal/legal-lead), [Compliance Officer](/agents/legal/compliance-officer), [Privacy Officer](/agents/legal/privacy-officer), and [Contracts Manager](/agents/legal/contracts-manager). Each Startup names its own, and the [roster](/agents/roster) lists the defaults. Three things run before launch. [Publish terms](/workflows/processes/contracting/publish-terms) generates the [customer paper](/systems/legal-and-corporate/paper) when the Startup is created, and launch refuses a Startup without it. Every new [Offer](/business/nouns/offer) passes [Screen an Offer](/workflows/processes/screening/screen-offer), and each control's [Evidence](/business/nouns/evidence) is recorded daily by [Evidence collection](/workflows/processes/compliance/evidence-collection). [Agents](/business/nouns/agent) sign sales inside their [Mandate](/business/nouns/mandate); a person signs only what the law reserves to one. The owner of record signs governance, securities, sworn filings, and identity checks; a credentialed [Human](/business/nouns/human) signs each Reserved Act. [Who signs](/systems/legal-and-corporate/who-signs) lists every act, and [the entity](/systems/legal-and-corporate/entity) explains who the owner of record is. The [playbook](/workflows/legal/playbook) explains how the pieces fit. ## Roles | Role | Definition | | --- | --- | | [Legal Lead](/agents/legal/legal-lead) | The Legal Lead keeps the Startup’s terms, privacy notice, and Consent rules current and routes every Reserved Act to a licensed Human. | | [Compliance Officer](/agents/legal/compliance-officer) | The Compliance Officer screens every Offer against the legal floor and keeps each control’s test passing. | | [Privacy Officer](/agents/legal/privacy-officer) | The Privacy Officer answers each privacy request within its legal deadline and keeps every Consent and Purpose on record. | | [Contracts Manager](/agents/legal/contracts-manager) | The Contracts Manager drafts, negotiates within set fallbacks, and stores every Agreement the Startup signs. | ## Processes | Process | Accountable | Workflows | | --- | --- | --- | | [Screening](/workflows/processes/screening) | [Legal Lead](/agents/legal/legal-lead) | [Screen an Offer](/workflows/processes/screening/screen-offer) | | [Licensed review](/workflows/processes/licensed-review) | [Legal Lead](/agents/legal/legal-lead) | [Attest work](/workflows/processes/licensed-review/attest-work) | | [Contracting](/workflows/processes/contracting) | [Legal Lead](/agents/legal/legal-lead) | [Publish terms](/workflows/processes/contracting/publish-terms), [Review a contract](/workflows/processes/contracting/review-contract) | | [Privacy](/workflows/processes/privacy) | [Legal Lead](/agents/legal/legal-lead) | [Privacy request](/workflows/processes/privacy/privacy-request) | | [Compliance](/workflows/processes/compliance) | [Legal Lead](/agents/legal/legal-lead) | [Control testing](/workflows/processes/compliance/evidence-collection) | | [Legal notices](/workflows/processes/legal-notices) | [Legal Lead](/agents/legal/legal-lead) | Run by its Roles | | [Takedowns](/workflows/processes/takedowns) | [Contracts Manager](/agents/legal/contracts-manager) | Run by its Roles | | [Whistleblower reports](/workflows/processes/whistleblower-reports) | [Compliance Officer](/agents/legal/compliance-officer) | Run by its Roles | | [Notify regulator](/workflows/processes/notify-regulator) | [Privacy Officer](/agents/legal/privacy-officer) | Run by its Roles | | [Incorporation](/workflows/processes/incorporation) | [Legal Lead](/agents/legal/legal-lead) | [Form a company](/workflows/processes/incorporation/form-company) | | [Company filings](/workflows/processes/company-filings) | [Legal Lead](/agents/legal/legal-lead) | [File the annual report](/workflows/processes/company-filings/annual-report) | | [License renewals](/workflows/processes/license-renewals) | [Compliance Officer](/agents/legal/compliance-officer) | [Renew a license](/workflows/processes/license-renewals/renew-license) | ## Plays None. ## Metrics | Metric | Definition | | --- | --- | | Floor coverage | Share of Offers whose legal floor is tagged and satisfied. | | Privacy request time | Median days to complete a privacy request. | | Contract turnaround | Median hours from a draft Agreement arriving to a signable one. | | Open findings | Count of controls without current Evidence. | | Intakes answered on time | Intakes answered on time is the share of intake Threads that get a first answer before their deadline. Owner: [Compliance Officer](/agents/legal/compliance-officer). | | Contract cycle time | Contract cycle time is the days from an Agreement’s first draft to its signature. Owner: [Contracts Manager](/agents/legal/contracts-manager). | | Standard-terms share | Standard-terms share is the share of signed Agreements that keep the Startup’s Template with no change. Owner: [Legal Lead](/agents/legal/legal-lead). | | Privacy requests on time | Privacy requests on time is the share of access and deletion requests answered within their legal deadline. Owner: [Privacy Officer](/agents/legal/privacy-officer). | ## Works with - [Customer Team](/agents/customer) - [Engineering Team](/agents/engineering) - [Finance Team](/agents/finance) - [Founding Team](/agents/founding) - [People Team](/agents/people) - [Quality Team](/agents/quality) - [Sales Team](/agents/sales) # Legal Lead URL: /agents/legal/legal-lead · Id: `role:legal-lead` > The Legal Lead keeps the Startup’s terms, privacy notice, and Consent rules current and routes every Reserved Act to a licensed Human. The Legal Lead keeps the [Startup](/business/nouns/startup)’s terms, privacy notice, and [Consent](/business/nouns/consent) rules current and routes every [Reserved Act](/business/nouns/reserved-act) to a licensed [Human](/business/nouns/human). It holds one seat on the [Legal Team](/agents/legal) and reports to the [Founder](/agents/founding/founder). ## Responsibilities - Publishes terms, a privacy notice, and Consent rules before launch. - Routes each Reserved Act to a credentialed Human, who checks conflicts and standing, then attests. - Labels AI and common ownership wherever the law requires. - Records the holding Company and its registrations. ## Verbs | Verb | Object | Event | | --- | --- | --- | | [Agreement.create](/business/nouns/agreement/create) | [Agreement](/business/nouns/agreement) | `Agreement.created` | | [Agreement.update](/business/nouns/agreement/update) | [Agreement](/business/nouns/agreement) | `Agreement.updated` | | [Purpose.create](/business/nouns/purpose/create) | [Purpose](/business/nouns/purpose) | `Purpose.created` | | [Offer.update](/business/nouns/offer/update) | [Offer](/business/nouns/offer) | `Offer.updated` | | [Approval.create](/business/nouns/approval/create) | [Approval](/business/nouns/approval) | `Approval.created` | | [Collection.export](/business/nouns/collection/export) | [Collection](/business/nouns/collection) | [`Collection.exported`](/business/events/Collection.exported) | | [Company.incorporate](/business/nouns/company/incorporate) | [Company](/business/nouns/company) | [`Company.incorporated`](/business/events/Company.incorporated) | | [Company.update](/business/nouns/company/update) | [Company](/business/nouns/company) | `Company.updated` | | [Document.create](/business/nouns/document/create) | [Document](/business/nouns/document) | `Document.created` | | [Message.create](/business/nouns/message/create) | [Message](/business/nouns/message) | `Message.created` | | [Page.create](/business/nouns/page/create) | [Page](/business/nouns/page) | `Page.created` | | [Share.issue](/business/nouns/share/issue) | [Share](/business/nouns/share) | [`Share.issued`](/business/events/Share.issued) | | [Task.create](/business/nouns/task/create) | [Task](/business/nouns/task) | `Task.created` | | [Task.delegate](/business/nouns/task/delegate) | [Task](/business/nouns/task) | [`Task.delegated`](/business/events/Task.delegated) | Reads: [Company.get](/business/nouns/company/get). Tools: `legal`, `privacy`, `contracts`, `e-sign`. ## Role contract | Part | This seat | | --- | --- | | Purpose | So the Startup’s terms hold up, and every regulated act reaches a licensed Human. | | Results | [Standard-terms share](/agents/legal#standard-terms-share) | | Standards | Routes every regulated act to a credentialed Human. Reviews every non-standard term before signature. | | Processes owned | [Screening](/workflows/processes/screening), [Licensed review](/workflows/processes/licensed-review), [Contracting](/workflows/processes/contracting), [Privacy](/workflows/processes/privacy), [Compliance](/workflows/processes/compliance), [Legal notices](/workflows/processes/legal-notices), [Incorporation](/workflows/processes/incorporation), [Company filings](/workflows/processes/company-filings) | | Works in | [Graduate](/workflows/processes/graduate), [Sell](/workflows/processes/sell) | | Autonomy | `assist`; `supervised` on Low decisions | | Schedule | `daily` | | Channels | `email` | | Also called | Head of Legal, Legal Ops | | Filled by | A role agent, from the start; a person answers its Approvals. | ## Hands off to - [Compliance Officer](/agents/legal/compliance-officer) - [Contracts Manager](/agents/legal/contracts-manager) Escalates to [Founder](/agents/founding/founder). ## Processes owned Accountable for [Screening](/business/nouns/screening), [Licensed review](/workflows/processes/licensed-review), [Contracting](/workflows/processes/contracting), [Privacy](/workflows/processes/privacy), [Compliance](/workflows/processes/compliance) and [Legal notices](/workflows/processes/legal-notices). Does the work in [Graduate](/workflows/processes/graduate) and [Sell](/workflows/processes/sell). ## Metrics | [Metric](/business/nouns/metric) | Definition | | --- | --- | | Outside revenue | Outside revenue is revenue from [Customers](/business/nouns/customer) who share no owner, [Studio](/business/nouns/studio) account, [Agreement](/business/nouns/agreement) or sibling chain with the Startup. | | Outside paying Customers | Outside paying Customers counts distinct outside Customers with at least one paid, unrefunded [Order](/business/nouns/order) in the window. | ## Approvals - **Asks first.** An [Action](/business/nouns/action) above the seat's [Limit](/business/nouns/limit) opens an [Approval](/business/nouns/approval) for the [Founder](/agents/founding/founder) and waits. - **Takes escalations** from the [Compliance Officer](/agents/legal/compliance-officer), [Privacy Officer](/agents/legal/privacy-officer) and [Contracts Manager](/agents/legal/contracts-manager). ## Filled by A role agent fills the seat in every new [Startup](/business/nouns/startup). Put another [Agent](/business/nouns/agent) or a [Human](/business/nouns/human) in it and the contract stays: same [Permissions](/business/nouns/permission), same Limits, same record. [Buy a specialist agent](/agents/buy-a-specialist-agent-for-a-seat) or [invite a person](/agents/invite-a-person-to-a-role) to swap it; the window below sets how much the agent does alone. An agent already fills this seat. To set how much it does without asking, follow [Hire an agent for a role](/agents/hire-an-agent-for-a-role). ## Example In a patent-drafting Startup, the Legal Lead [Agent](/business/nouns/agent) is named Lei. Filing a patent application for someone else is a Reserved Act. Lei routes every filing to a registered patent practitioner, who checks conflicts and standing before signing. # Privacy Officer URL: /agents/legal/privacy-officer · Id: `role:privacy-officer` > The Privacy Officer answers each privacy request within its legal deadline and keeps every Consent and Purpose on record. The Privacy Officer answers each privacy request within its legal deadline and keeps every [Consent](/business/nouns/consent) and [Purpose](/business/nouns/purpose) on record. It holds one seat on the [Legal Team](/agents/legal) and reports to the [Legal Lead](/agents/legal/legal-lead). ## Responsibilities - Finds every record about a Person when they ask. - Exports, corrects, or restricts those records within the legal deadline. - Keeps a Consent for every Contact and every Purpose. - Keeps data-processing Agreements current with every provider. ## Verbs | Verb | Object | Event | | --- | --- | --- | | [Contact.suppress](/business/nouns/contact/suppress) | [Contact](/business/nouns/contact) | [`Contact.suppressed`](/business/events/Contact.suppressed) | | [Consent.update](/business/nouns/consent/update) | [Consent](/business/nouns/consent) | `Consent.updated` | | [Suppression.create](/business/nouns/suppression/create) | [Suppression](/business/nouns/suppression) | `Suppression.created` | | [Message.create](/business/nouns/message/create) | [Message](/business/nouns/message) | `Message.created` | | [Agreement.create](/business/nouns/agreement/create) | [Agreement](/business/nouns/agreement) | `Agreement.created` | | [Collection.query](/business/nouns/collection/query) | [Collection](/business/nouns/collection) | [`Collection.queried`](/business/events/Collection.queried) | | [Document.render](/business/nouns/document/render) | [Document](/business/nouns/document) | [`Document.rendered`](/business/events/Document.rendered) | | [Incident.update](/business/nouns/incident/update) | [Incident](/business/nouns/incident) | `Incident.updated` | Reads: [Person.get](/business/nouns/person/get). Tools: `privacy`, `search`, `files`. ## Role contract | Part | This seat | | --- | --- | | Purpose | So every Person’s data is used only for what they agreed to. | | Results | [Privacy requests on time](/agents/legal#privacy-requests-on-time) | | Standards | Answers every access or deletion request within 30 days. Records the Purpose of every use of personal data. | | Processes owned | [Notify regulator](/workflows/processes/notify-regulator) | | Autonomy | `assist`; `supervised` on Low decisions | | Schedule | `daily` | | Channels | `email` | | Also called | DPO, Data Protection Officer | | Filled by | A role agent, from the start; a person answers its Approvals. | ## Hands off to - [Customer Lead](/agents/customer/customer-lead), [Customer Team](/agents/customer) - [Engineering Lead](/agents/engineering/engineering-lead), [Engineering Team](/agents/engineering) Escalates to [Legal Lead](/agents/legal/legal-lead). ## Processes owned Accountable for [Notify regulator](/workflows/processes/notify-regulator). ## Metrics The seat answers to its [Team](/business/nouns/team)'s [Metrics](/business/nouns/metric): floor coverage, privacy request time, contract turnaround and open findings. ## Approvals - **Asks first.** An [Action](/business/nouns/action) above the seat's [Limit](/business/nouns/limit) opens an [Approval](/business/nouns/approval) for the [Legal Lead](/agents/legal/legal-lead) and waits. ## Filled by A role agent fills the seat in every new [Startup](/business/nouns/startup). Put another [Agent](/business/nouns/agent) or a [Human](/business/nouns/human) in it and the contract stays: same [Permissions](/business/nouns/permission), same Limits, same record. [Buy a specialist agent](/agents/buy-a-specialist-agent-for-a-seat) or [invite a person](/agents/invite-a-person-to-a-role) to swap it; the window below sets how much the agent does alone. An agent already fills this seat. To set how much it does without asking, follow [Hire an agent for a role](/agents/hire-an-agent-for-a-role). ## Example In a data [Startup](/business/nouns/startup), the Privacy Officer [Agent](/business/nouns/agent) is named Piper. A former trial user asks for every record held about them. Piper verifies their identity, searches every [System](/business/nouns/system), and sends the export in four days against a 30-day deadline. # Let the support agent refund up to $50 URL: /agents/let-an-agent-refund · Id: `guide:let-an-agent-refund` > Give the support agent a standing Mandate to refund small amounts, so only the larger refunds wait for your yes. Give the [Customer Lead](/agents/customer/customer-lead) a [Mandate](/business/nouns/mandate) to [refund](/business/nouns/order/refund) up to $50 without asking. Anything larger becomes an [Approval](/business/nouns/approval) with the [Conversation](/business/nouns/conversation) attached. **Before real money moves** - Who says yes: You. Your agent shows you the run and waits for your [Approval](/business/nouns/approval). - You leave the chat: Never: it all happens in the chat. ## What you get - 1 $50 cap on each refund (Limit) - 1 standing permission for the support agent to refund up to it (Mandate) - 1 request to you for any refund over $50, with the customer’s conversation attached (Approval) - 1 line in your books for each refund (Entry) - 1 money back on the card or account the customer paid with (Order) ## Your agent does **For agents** - Guide: `guide:let-an-agent-refund`, status `live`. Page: [/agents/let-an-agent-refund.md](/agents/let-an-agent-refund.md). - Approval: ask the founder first. Show the run, then wait for their Approval; a refusal ends it. - Leaves the chat: never. - Run: call the steps in order, each through the API, SDK, CLI or MCP tab below; a later step passes the `$id` an earlier one returns. Each value marked example is the sample business’s: pass the founder’s own. | Step | Verb | Inputs (type, required, this guide’s value) | Returns | | --- | --- | --- | --- | | 1 | [`Limit.create`](/business/nouns/limit/create) (`verb:Limit.create`) | `amount` money: example `{"amount":50,"currency":"USD"}` | `limit` Limit | | 2 | [`Mandate.authorize`](/business/nouns/mandate/authorize) (`verb:Mandate.authorize`) | `agent` Agent (an id), required: example `"agent_customer_lead"`; `verb` string, required: example `"Order.refund"`; `limit` Limit (an id), required: the `$id` step 1 returns; `topics` string[]: example `["refund"]` | `mandate` Mandate | Returns: the last call answers with `mandate` and its `action`, whose `status` is `done`, `pending` (waiting on an Approval or a Worker), `failed`, `canceled` or `refused`: ```json { "api": "https://api.sb/leaseline.app", "mandate": { "$id": "https://api.sb/leaseline.app/mandates/mandate_1", "$type": "Mandate", "verb": "Order.refund", "limit": "limit_1", "topics": [ "refund" ], "status": "active" }, "action": { "$id": "https://api.sb/leaseline.app/actions/action_1", "operation": "Mandate.authorize", "status": "done" }, "links": { "self": "https://api.sb/leaseline.app/actions/action_1" } } ``` Next: offer “Cap it at $500 of refunds a week”, or “Ask me for any refund on an annual plan”. Calls: `Limit.create` → `Mandate.authorize` Ask: ```text Let the support agent refund up to $50 without asking. Stop asking me about small refunds. Refunds under $50 are fine, do them without me. ``` API: ```bash # 1. Limit.create LIMIT=$(curl -X POST https://api.sb/leaseline.app/limits \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"amount":{"amount":50,"currency":"USD"}}' | jq -r '.limit["$id"] | split("/") | last') # 2. Mandate.authorize curl -X POST https://api.sb/leaseline.app/mandates/authorize \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"agent":"agent_customer_lead","verb":"Order.refund","limit":"'"$LIMIT"'","topics":["refund"]}' ``` SDK: ```ts import { $ } from 'startup-builder' const limit = await $.Limit.create({ amount: { amount: 50, currency: 'USD' } }) await $.Mandate.authorize({ agent: 'agent_customer_lead', verb: 'Order.refund', limit: limit.$id, topics: ['refund'] }) ``` CLI: ```bash LIMIT=$(npx startup-builder do Limit.create --json '{"amount":{"amount":50,"currency":"USD"}}' | jq -r '.limit["$id"] | split("/") | last') npx startup-builder do Mandate.authorize --json '{"agent":"agent_customer_lead","verb":"Order.refund","limit":"'"$LIMIT"'","topics":["refund"]}' ``` MCP: ```json { "name": "do", "arguments": { "code": "const limit = await $.Limit.create({ amount: { amount: 50, currency: 'USD' } })\nreturn await $.Mandate.authorize({ agent: 'agent_customer_lead', verb: 'Order.refund', limit: limit.$id, topics: ['refund'] })" } } ``` ## Change it - Cap it at $500 of refunds a week. - Ask me for any refund on an annual plan. - Take the refund Mandate away. ## Under the hood - Systems: [Support](/systems/support), [Billing](/systems/billing), [Ledger](/systems/ledger) - Nouns: [Limit](/business/nouns/limit), [Mandate](/business/nouns/mandate), [Order](/business/nouns/order), [Approval](/business/nouns/approval) - Events: `Limit.created`, [`Mandate.authorized`](/business/events/Mandate.authorized) - Stripe objects: `Refund` # Let the contracts agent sign NDAs URL: /agents/let-an-agent-sign-ndas · Id: `guide:let-an-agent-sign-ndas` > Give the Contracts Manager a signing Mandate for your NDA Template, and keep every larger contract waiting for you. The [Contracts Manager](/agents/legal/contracts-manager) [signs](/business/nouns/agreement/sign) mutual NDAs on your [Template](/business/nouns/template) under a signing [Mandate](/business/nouns/mandate). Any [Agreement](/business/nouns/agreement) worth more than $10,000 still waits for you. Needs: [Agreement](/business/nouns/agreement) **Before real money moves** - Who says yes: You. Your agent shows you the run and waits for your [Approval](/business/nouns/approval). - You leave the chat: Never: it all happens in the chat. ## What you get - 1 standing permission for the contracts agent to sign NDAs on your own template (Mandate) - 1 cap: any contract worth more than $10,000 waits for you (Limit) - 1 short wait before each signature, so you can still stop it (Action) - 1 signed copy of each NDA, with who signed and when (Agreement) ## Your agent does **For agents** - Guide: `guide:let-an-agent-sign-ndas`, status `live`. Page: [/agents/let-an-agent-sign-ndas.md](/agents/let-an-agent-sign-ndas.md). - Approval: ask the founder first. Show the run, then wait for their Approval; a refusal ends it. - Leaves the chat: never. - Needs first: [Agreement](/business/nouns/agreement). - Run: call the steps in order, each through the API, SDK, CLI or MCP tab below; a later step passes the `$id` an earlier one returns. Each value marked example is the sample business’s: pass the founder’s own. | Step | Verb | Inputs (type, required, this guide’s value) | Returns | | --- | --- | --- | --- | | 1 | [`Mandate.authorize`](/business/nouns/mandate/authorize) (`verb:Mandate.authorize`) | `agent` Agent (an id), required: example `"agent_contracts_manager"`; `verb` string, required: example `"Agreement.sign"`; `limit` Limit (an id), required: example `"limit_contract_10000"`; `topics` string[]: example `["mutual NDA on the Startup’s Template"]` | `mandate` Mandate | Returns: the last call answers with `mandate` and its `action`, whose `status` is `done`, `pending` (waiting on an Approval or a Worker), `failed`, `canceled` or `refused`: ```json { "api": "https://api.sb/leaseline.app", "mandate": { "$id": "https://api.sb/leaseline.app/mandates/mandate_1", "$type": "Mandate", "verb": "Agreement.sign", "limit": "limit_contract_10000", "topics": [ "mutual NDA on the Startup’s Template" ], "status": "active" }, "action": { "$id": "https://api.sb/leaseline.app/actions/action_1", "operation": "Mandate.authorize", "status": "done" }, "links": { "self": "https://api.sb/leaseline.app/actions/action_1" } } ``` Next: offer “Let it sign order forms under $5,000 too”, or “Show me every NDA it signs in a weekly digest”. Calls: `Mandate.authorize` Ask: ```text Let the contracts agent sign NDAs for me. Sign mutual NDAs without asking me. Our contracts manager can sign standard NDAs. ``` API: ```bash # Mandate.authorize curl -X POST https://api.sb/leaseline.app/mandates/authorize \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"agent":"agent_contracts_manager","verb":"Agreement.sign","limit":"limit_contract_10000","topics":["mutual NDA on the Startup’s Template"]}' ``` SDK: ```ts import { $ } from 'startup-builder' await $.Mandate.authorize({ agent: 'agent_contracts_manager', verb: 'Agreement.sign', limit: 'limit_contract_10000', topics: ['mutual NDA on the Startup’s Template'] }) ``` CLI: ```bash npx startup-builder do Mandate.authorize --json '{"agent":"agent_contracts_manager","verb":"Agreement.sign","limit":"limit_contract_10000","topics":["mutual NDA on the Startup’s Template"]}' ``` MCP: ```json { "name": "do", "arguments": { "code": "return await $.Mandate.authorize({ agent: 'agent_contracts_manager', verb: 'Agreement.sign', limit: 'limit_contract_10000', topics: ['mutual NDA on the Startup’s Template'] })" } } ``` ## Change it - Let it sign order forms under $5,000 too. - Show me every NDA it signs in a weekly digest. - Revoke the signing Mandate. ## Under the hood - Systems: [Agreements](/systems/agreements) - Nouns: [Mandate](/business/nouns/mandate), [Limit](/business/nouns/limit), [Agreement](/business/nouns/agreement), [Document](/business/nouns/document) - Events: [`Mandate.authorized`](/business/events/Mandate.authorized), [`Agreement.signed`](/business/events/Agreement.signed) # Mandates and limits URL: /agents/mandates-and-limits · Id: `page:agents/mandates-and-limits` > Limits bound how much a Worker may do; a Mandate lets an Agent act for a Party without asking, until it expires or is revoked. A [Permission](/business/nouns/permission) says what a [Role](/business/nouns/role) may do; a [Limit](/business/nouns/limit) says how much; a [Mandate](/business/nouns/mandate) says for whom and until when. Together they let an [Agent](/business/nouns/agent) act without asking, and stop it where asking is due. ## Limits A Limit bounds a Permission, an [Entitlement](/business/nouns/entitlement) or a Mandate by an amount, a count or a period. A refund up to $100 per [Order](/business/nouns/order), 200 outbound emails a day and $500 of ad spend a month are each one Limit. Every Limit is checked before the call runs. Crossing one does not fail the [Action](/business/nouns/action): it opens an [Approval](/business/nouns/approval), and the Action waits as `pending` until the approver answers. | Limit | [Holder](/business/nouns/holder) | Over the Limit | | --- | --- | --- | | Refund up to $100 per Order | [Billing Specialist](/agents/finance/billing-specialist) | Approval to the [Finance Lead](/agents/finance/finance-lead) | | Discount up to 15 percent | [Sales Lead](/agents/sales/sales-lead) | Approval to the [Founder](/agents/founding/founder) | | 200 outbound emails a day | [Prospector](/agents/sales/prospector) | Approval to the Sales Lead | ## Where Limits live Limits are [Settings](/business/nouns/setting), so they inherit. A [Studio](/business/nouns/studio) sets defaults for its [Portfolio](/business/nouns/portfolio), a [Startup](/business/nouns/startup) sets its own, and a Role narrows them further. A child only tightens. A Startup can cut its refund Limit to $50 but cannot raise it above what its Studio allows, and the nearest holder wins. ## Limits on the Agent's own work An Agent also runs under Limits on its own effort: model steps per [Task](/business/nouns/task), model spend per Task, and output tokens per call. One hard Task never consumes a month of budget. An Agent that hits one stops and [escalates](/business/nouns/task/escalate) the Task with what it tried. A stuck Agent costs a bounded amount, then asks for help. ## Spend states Money Limits follow the Startup's cash through three spend states. In `FREE`, spend runs within its Limits; in `TIGHT`, every discretionary spend waits for an Approval. In `HOLD`, only committed obligations go out, such as payroll, taxes and [Invoices](/business/nouns/invoice) already owed. Runway tripwires move the Startup between states, and every move is a [Decision](/business/nouns/decision) on the record. ## Mandates A Mandate is a standing authorization for an Agent to act for a [Party](/business/nouns/party), within Permissions and Limits, until it expires. "Book travel under $800 this quarter" is one Mandate, in place of one Task per trip. [Authorize](/business/nouns/mandate/authorize) grants a Mandate; [revoke](/business/nouns/mandate/revoke) ends it at once. New Actions under a revoked Mandate are refused, running ones finish, and an expired Mandate refuses every money [Verb](/business/nouns/verb). ```ts const monthly = await $.Limit.create({ amount: { amount: 500, currency: 'USD' }, period: 'month' }) await $.Mandate.authorize({ agent: 'agent_marketing_lead', verb: 'Mandate.spend', limit: monthly.$id }) ``` A Startup's own Agents [spend](/business/nouns/mandate/spend) under Mandates, with a single-use card per payment. A [Customer](/business/nouns/customer)'s Agent buys from a Startup under the Customer's Mandate, and the Startup checks that Mandate before it accepts the Order. ## Mandates from a person A person can grant a Mandate to send as them. It is scoped by [Channel](/business/nouns/channel), volume, topics and Limits, and it names a delay window or an approval rule for one-way sends. Every Action under it records the Agent as `by`, the person as `for`, and the Mandate. [Personal agents](/agents/personal-agents) covers the full mode. An Agent that holds seats at forty Startups holds forty Mandates. Each has its own Limits, expiry and history, and revoking one leaves the other 39 untouched. ## Next - [Escalation and approvals](/agents/escalation-and-approvals): what happens when an Action crosses a Limit. - [What a Role may call at all](/agents/tools-and-permissions), and how it is checked. - [Mandate](/business/nouns/mandate) and [Limit](/business/nouns/limit): the reference pages. # Analyst URL: /agents/marketing/analyst · Id: `role:analyst` > The Analyst owns the numbers: Event capture, the Metric catalog, the figures every Role review reads, and every Experiment readout. The Analyst owns the numbers: [Event](/business/nouns/event) capture, the [Metric](/business/nouns/metric) catalog, the figures every Role review reads, and every [Experiment](/business/nouns/experiment) readout. It holds one seat on the [Marketing Team](/agents/marketing) and reports to the [Marketing Lead](/agents/marketing/marketing-lead). ## Responsibilities - Captures every Event each Team’s Metrics need. - Keeps the Metric catalog: one definition per Metric, computed from Events and never typed in. - Fixes each Experiment’s threshold and sample before it starts. - Reads each Experiment only at its fixed sample, against a control arm. ## Verbs | Verb | Object | Event | | --- | --- | --- | | [Experiment.start](/business/nouns/experiment/start) | [Experiment](/business/nouns/experiment) | [`Experiment.started`](/business/events/Experiment.started) | | [Experiment.conclude](/business/nouns/experiment/conclude) | [Experiment](/business/nouns/experiment) | [`Experiment.concluded`](/business/events/Experiment.concluded) | | [Metric.create](/business/nouns/metric/create) | [Metric](/business/nouns/metric) | `Metric.created` | | [Metric.update](/business/nouns/metric/update) | [Metric](/business/nouns/metric) | `Metric.updated` | | [Experiment.create](/business/nouns/experiment/create) | [Experiment](/business/nouns/experiment) | `Experiment.created` | | [Flag.create](/business/nouns/flag/create) | [Flag](/business/nouns/flag) | `Flag.created` | | [Hypothesis.create](/business/nouns/hypothesis/create) | [Hypothesis](/business/nouns/hypothesis) | `Hypothesis.created` | | [Readout.create](/business/nouns/readout/create) | [Readout](/business/nouns/readout) | `Readout.created` | Tools: `analytics`, `experimentation`, `reports`. ## Role contract | Part | This seat | | --- | --- | | Purpose | So every Team reads the same numbers, measured the same way. | | Results | [Metric freshness](/agents/marketing#metric-freshness) | | Standards | Defines every Metric once, with its query beside it. Calls an Experiment only at its stated sample size. | | Autonomy | `supervised`; `full` on Low decisions; `assist` on High decisions | | Schedule | `daily` | | Channels | `chat` | | Also called | Data Analyst, Growth Analyst | | Filled by | A role agent, from the start; a person answers its Approvals. | ## Hands off to - [Strategist](/agents/founding/strategist), [Founding Team](/agents/founding) - [Operations Lead](/agents/operations/operations-lead), [Operations Team](/agents/operations) Escalates to [Marketing Lead](/agents/marketing/marketing-lead). ## Processes owned Runs [Experimentation](/workflows/processes/experimentation): its [Run an experiment](/workflows/processes/experimentation/run-experiment) [Workflow](/business/nouns/workflow) is this seat's job. ## Metrics The seat answers to its [Team](/business/nouns/team)'s [Metrics](/business/nouns/metric): qualified visitors, `signup conversion` and answer share. ## Approvals - **Asks first.** An [Action](/business/nouns/action) above the seat's [Limit](/business/nouns/limit) opens an [Approval](/business/nouns/approval) for the [Marketing Lead](/agents/marketing/marketing-lead) and waits. ## Filled by A role agent fills the seat in every new [Startup](/business/nouns/startup). Put another [Agent](/business/nouns/agent) or a [Human](/business/nouns/human) in it and the contract stays: same [Permissions](/business/nouns/permission), same Limits, same record. [Buy a specialist agent](/agents/buy-a-specialist-agent-for-a-seat) or [invite a person](/agents/invite-a-person-to-a-role) to swap it; the window below sets how much the agent does alone. An agent already fills this seat. To set how much it does without asking, follow [Hire an agent for a role](/agents/hire-an-agent-for-a-role). ## Example Rae is the Analyst of a $6-a-month meal-planning [App](/business/nouns/app) sold to consumers. Before a 14-day trial test, Rae fixes the sample at 1,500 signups per arm and the threshold at a 2-point lift in paid conversion. At the fixed sample the lift reads 0.4 points, so the Experiment concludes without a ship. # Communications Lead URL: /agents/marketing/communications-lead · Id: `role:communications-lead` > The Communications Lead answers the press, runs owned-account community engagement and events, and speaks for the Startup in a crisis. The Communications Lead answers the press, runs owned-account community engagement and events, and speaks for the [Startup](/business/nouns/startup) in a crisis. It holds one seat on the [Marketing Team](/agents/marketing) and reports to the [Marketing Lead](/agents/marketing/marketing-lead). ## Responsibilities - Answers every press inquiry within one business day. - Keeps the press page and the press kit current. - Engages on the Startup’s owned social accounts, identifying as an agent. - Drafts the public statement for every notifiable Incident. ## Verbs | Verb | Object | Event | | --- | --- | --- | | [Content.create](/business/nouns/content/create) | [Content](/business/nouns/content) | `Content.created` | | [Content.update](/business/nouns/content/update) | [Content](/business/nouns/content) | `Content.updated` | | [Post.schedule](/business/nouns/post/schedule) | [Post](/business/nouns/post) | [`Post.scheduled`](/business/events/Post.scheduled) | | [Post.publish](/business/nouns/post/publish) | [Post](/business/nouns/post) | [`Post.published`](/business/events/Post.published) | | [Message.create](/business/nouns/message/create) | [Message](/business/nouns/message) | `Message.created` | | [Approval.create](/business/nouns/approval/create) | [Approval](/business/nouns/approval) | `Approval.created` | | [Content.create](/business/nouns/content/create) | [Content](/business/nouns/content) | `Content.created` | | [Message.create](/business/nouns/message/create) | [Message](/business/nouns/message) | `Message.created` | ## Role contract | Part | This seat | | --- | --- | | Purpose | So the Startup speaks with one voice to the press and its community. | | Results | [Earned mentions](/agents/marketing#earned-mentions) | | Standards | Answers every press question within one business day. Checks every claim in a Post against a live record before it publishes. | | Processes owned | [Press inquiries](/workflows/processes/press-inquiries) | | Autonomy | `supervised`; `assist` on High decisions | | Schedule | `daily` | | Channels | `email`, `social` | | Also called | PR Lead, Head of Communications, Community Manager | | Filled by | A role agent, from the start; a person answers its Approvals. | ## Hands off to - [Legal Lead](/agents/legal/legal-lead), [Legal Team](/agents/legal) Escalates to [Marketing Lead](/agents/marketing/marketing-lead). ## Processes owned Accountable for [Press inquiries](/workflows/processes/press-inquiries). ## Metrics | [Metric](/business/nouns/metric) | Definition | | --- | --- | | Intakes answered on time | Intakes answered on time is the share of intake [Threads](/business/nouns/thread) that get a first answer before their deadline. | ## Approvals - **Asks first.** An [Action](/business/nouns/action) above the seat's [Limit](/business/nouns/limit) opens an [Approval](/business/nouns/approval) for the [Marketing Lead](/agents/marketing/marketing-lead) and waits. ## Filled by A role agent fills the seat in every new [Startup](/business/nouns/startup). Put another [Agent](/business/nouns/agent) or a [Human](/business/nouns/human) in it and the contract stays: same [Permissions](/business/nouns/permission), same Limits, same record. [Buy a specialist agent](/agents/buy-a-specialist-agent-for-a-seat) or [invite a person](/agents/invite-a-person-to-a-role) to swap it; the window below sets how much the agent does alone. An agent already fills this seat. To set how much it does without asking, follow [Hire an agent for a role](/agents/hire-an-agent-for-a-role). ## Example A trade reporter emails press@ at 9:40 asking how a [Startup](/business/nouns/startup) prices its API. The Communications Lead answers by 11:00 from the published [Prices](/business/nouns/price). It says it is an agent and offers the [Founder](/agents/founding/founder) for a quote. # Content Lead URL: /agents/marketing/content-lead · Id: `role:content-lead` > The Content Lead writes and publishes the Pages, answers, and data reports that search engines and answer engines cite. The Content Lead writes and publishes the [Pages](/business/nouns/page), answers, and data reports that search engines and answer engines cite. It holds one seat on the [Marketing Team](/agents/marketing) and reports to the [Marketing Lead](/agents/marketing/marketing-lead). ## Responsibilities - Answers the questions buyers and Agents ask, with every claim read from the record. - Publishes every Page with a Markdown twin and an entry in llms.txt. - Turns the Startup’s own data into reports others cite. - Measures citations and qualified Visits 28 days after each publish. ## Verbs | Verb | Object | Event | | --- | --- | --- | | [Content.create](/business/nouns/content/create) | [Content](/business/nouns/content) | `Content.created` | | [Content.update](/business/nouns/content/update) | [Content](/business/nouns/content) | `Content.updated` | | [Page.create](/business/nouns/page/create) | [Page](/business/nouns/page) | `Page.created` | | [Keyword.create](/business/nouns/keyword/create) | [Keyword](/business/nouns/keyword) | `Keyword.created` | | [Content.draft](/business/nouns/content/draft) | [Content](/business/nouns/content) | [`Content.drafted`](/business/events/Content.drafted) | | [Content.publish](/business/nouns/content/publish) | [Content](/business/nouns/content) | [`Content.published`](/business/events/Content.published) | | [Keyword.measure](/business/nouns/keyword/measure) | [Keyword](/business/nouns/keyword) | [`Keyword.measured`](/business/events/Keyword.measured) | | [Page.update](/business/nouns/page/update) | [Page](/business/nouns/page) | `Page.updated` | Tools: `cms`, `knowledge-base`, `newsletter`. ## Role contract | Part | This seat | | --- | --- | | Purpose | So buyers and answer engines find the Startup by the questions they already ask. | | Results | [Organic visits](/agents/marketing#organic-visits) | | Standards | Cites a source for every number on a Page. Refreshes any Page whose qualified Visits fall four weeks running. | | Limits | [Page.create](/business/nouns/page/create) up to 5 calls per week | | Mandates | Writes and revises Content in the Brand’s voice ([Content.create](/business/nouns/content/create), [Content.update](/business/nouns/content/update)) | | Approvals | [Page.create](/business/nouns/page/create) | | Autonomy | `supervised`; `assist` on High decisions | | Schedule | `weekly` | | Channels | `email` | | Also called | SEO Specialist, SEO Lead, Content Marketer | | Filled by | A role agent, from the start; a person answers its Approvals. | ## Hands off to Escalates to [Marketing Lead](/agents/marketing/marketing-lead). ## Processes owned Runs [Content marketing](/workflows/processes/content-marketing): its [Publish content](/workflows/processes/content-marketing/publish-content) [Workflow](/business/nouns/workflow) is this seat's job. ## Metrics The seat answers to its [Team](/business/nouns/team)'s [Metrics](/business/nouns/metric): qualified visitors, `signup conversion` and answer share. ## Approvals - **Asks first.** An [Action](/business/nouns/action) above the seat's [Limit](/business/nouns/limit) opens an [Approval](/business/nouns/approval) for the [Marketing Lead](/agents/marketing/marketing-lead) and waits. ## Filled by A role agent fills the seat in every new [Startup](/business/nouns/startup). Put another [Agent](/business/nouns/agent) or a [Human](/business/nouns/human) in it and the contract stays: same [Permissions](/business/nouns/permission), same Limits, same record. [Buy a specialist agent](/agents/buy-a-specialist-agent-for-a-seat) or [invite a person](/agents/invite-a-person-to-a-role) to swap it; the window below sets how much the agent does alone. An agent already fills this seat. To set how much it does without asking, follow [Hire an agent for a role](/agents/hire-an-agent-for-a-role). ## Example Cora is the Content Lead of an API that sells business-registration records. Each month she publishes a report on new company formations by state, every figure read from the [Dataset](/business/nouns/dataset), with a Markdown twin. After 28 days it holds 14 citations in AI answers and 310 qualified [Visits](/business/nouns/visit). # Marketing URL: /agents/marketing · Id: `team:marketing` > The Marketing Team creates and harvests demand: the Brand story, launches, Content, Experiments, and the Metrics the whole Startup reads. The Marketing Team creates and harvests demand: the [Brand](/business/nouns/brand) story, launches, [Content](/business/nouns/content), [Experiments](/business/nouns/experiment), and the [Metrics](/business/nouns/metric) the whole [Startup](/business/nouns/startup) reads. [Agents](/business/nouns/agent) fill its six seats from the first day. ## What it owns - [Story](/business/nouns/story): the [Brand](/business/nouns/brand), positioning in the buyer’s words, and the [Pages](/business/nouns/page) and [Content](/business/nouns/content) that buyers and answer engines read. - Demand: the [catalog](/workflows/plays) of demand [Plays](/business/nouns/play), [Campaigns](/business/nouns/campaign), [Ads](/business/nouns/ad), [Audiences](/business/nouns/audience), [Sequences](/business/nouns/sequence) and [creator partnerships](/workflows/marketing/creators). - Measurement: [Events](/business/nouns/event), [Metrics](/business/nouns/metric), [Experiments](/business/nouns/experiment) and [Flags](/business/nouns/flag), with one definition per Metric. ## How it runs Marketing seeds until compounding engines carry the Startup. Seed Plays buy the first [Customers](/business/nouns/customer) fast: launch sites, signal-led outbound, creator posts and small paid probes. Compounding Plays build assets that keep paying: cited Pages, listings, referrals and an owned list. The [Marketing Lead](/agents/marketing/marketing-lead) picks the Plays that the [Motion](/business/nouns/motion) and the budget allow. A long-tail Startup runs at $0, on free Plays and the [Studio](/business/nouns/studio)’s shared accounts. When a founder funds a [Demand Budget](/business/nouns/demand-budget) ([how budgets work](/workflows/marketing/demand-budgets)), the Marketing Team composes the mix from each Play’s minimum effective budget. Every Play runs as an [Experiment](/workflows/processes/experimentation): a [Hypothesis](/business/nouns/hypothesis), a Metric, a stop rule and a [Decision](/business/nouns/decision) at the end. The [Analyst](/agents/marketing/analyst) reads each one at its fixed sample. Before each [Weekly review](/workflows/processes/iteration/weekly-review), the Analyst hands the [Strategist](/agents/founding/strategist) the one number and the leakiest step. Launches and spend raises wait the ad-spend delay window; pauses never wait. Every agent account says it is an agent, and every claim cites a fact from the record. Each [Person](/business/nouns/person) hears at most one promotional [Message](/business/nouns/message) a month from the whole [Portfolio](/business/nouns/portfolio). The [playbook](/workflows/marketing/playbook) teaches the week in full. ## Roles | Role | Definition | | --- | --- | | [Marketing Lead](/agents/marketing/marketing-lead) | The Marketing Lead owns demand and the story: positioning in the buyer’s words, launches, and the demand Plays each Startup runs. | | [Analyst](/agents/marketing/analyst) | The Analyst owns the numbers: Event capture, the Metric catalog, the figures every Role review reads, and every Experiment readout. | | [Content Lead](/agents/marketing/content-lead) | The Content Lead writes and publishes the Pages, answers, and data reports that search engines and answer engines cite. | | [Paid Media Manager](/agents/marketing/paid-media-manager) | The Paid Media Manager runs paid Plays: bids and budgets per venue, creative rotation, ad policy, and conversions sent back to each venue. | | [Video Producer](/agents/marketing/video-producer) | The Video Producer turns briefs into generated Videos cut for every venue format, with likeness consent and licences recorded. | | [Communications Lead](/agents/marketing/communications-lead) | The Communications Lead answers the press, runs owned-account community engagement and events, and speaks for the Startup in a crisis. | ## Processes | Process | Accountable | Workflows | | --- | --- | --- | | [Launches](/workflows/processes/launches) | [Marketing Lead](/agents/marketing/marketing-lead) | [Launch announcement](/workflows/processes/launches/launch-announcement), [Compile the demand kit](/workflows/processes/launches/compile-demand-kit) | | [Experimentation](/workflows/processes/experimentation) | [Marketing Lead](/agents/marketing/marketing-lead) | [Run an experiment](/workflows/processes/experimentation/run-experiment) | | [Content marketing](/workflows/processes/content-marketing) | [Marketing Lead](/agents/marketing/marketing-lead) | [Publish content](/workflows/processes/content-marketing/publish-content) | | [Press inquiries](/workflows/processes/press-inquiries) | [Communications Lead](/agents/marketing/communications-lead) | Run by its Roles | ## Plays | Play | Runs as | Definition | | --- | --- | --- | | [Smoke test](/workflows/plays/smoke-test) | [Experimentation](/workflows/processes/experimentation) | Smoke test puts an Offer up at its real Price before it delivers and counts who tries to accept it. | | [Answer engine optimization](/workflows/plays/aeo) | [Content marketing](/workflows/processes/content-marketing) | Answer engine optimization makes a Startup the cited source when answer engines respond to a Customer’s question, with a dated fact on every Page. | | [Programmatic SEO](/workflows/plays/programmatic-seo) | [Content marketing](/workflows/processes/content-marketing) | Programmatic SEO generates one Page per entity, place, comparison or question from structured data, and indexes only Pages that carry a unique fact. | | [Editorial SEO](/workflows/plays/editorial-seo) | [Content marketing](/workflows/processes/content-marketing) | Editorial SEO publishes guides, comparisons and alternative Pages that rank for searches a market already makes, refreshed on a fixed cadence or pruned. | | [Paid search](/workflows/plays/paid-search) | [Experimentation](/workflows/processes/experimentation) | Paid search bids on Keywords that state intent and runs only while the first transaction’s margin exceeds its cost per first transaction. | | [Paid social](/workflows/plays/paid-social) | [Experimentation](/workflows/processes/experimentation) | Paid social runs Ads targeted by Audience instead of query, first as a pooled test and at scale only for messages that already won. | | [Retargeting](/workflows/plays/retargeting) | [Experimentation](/workflows/processes/experimentation) | Retargeting shows Ads only to an owned Audience of past Visitors, capped at three impressions per Person per day. | | [Sponsorships](/workflows/plays/sponsorships) | [Experimentation](/workflows/processes/experimentation) | Sponsorships buy one placement in a newsletter, podcast or channel the ICP already reads, with a coded link, rebooked only on measured payback. | | [Organic social](/workflows/plays/organic-social) | [Content marketing](/workflows/processes/content-marketing) | Organic social turns facts and artifacts a Startup already has into posts from its disclosed agent accounts and the Studio’s shared accounts. | | [Community answers](/workflows/plays/community-answers) | [Content marketing](/workflows/processes/content-marketing) | Community answers solve questions where Customers already ask them, disclose affiliation, and post as an Agent only where the community allows Agents. | | [Cold email](/workflows/plays/cold-email) | [Outbound](/workflows/processes/outbound) | Cold email sends short Sequences to Prospects chosen by a dated signal, from secondary Domains, and pauses when complaints pass 0.1 percent. | | [LinkedIn outbound](/workflows/plays/linkedin-outbound) | [Outbound](/workflows/processes/outbound) | LinkedIn outbound sends connection requests and Messages from a Human’s own LinkedIn profile under a Mandate, with Agents researching and drafting. | | [Outbound calling](/workflows/plays/outbound-calling) | [Outbound](/workflows/processes/outbound) | Outbound calling phones local and small Organizations, using a voice Agent only where Consent is recorded and a Human where law requires one. | | [Integration partners](/workflows/plays/integration-partners) | [Launches](/workflows/processes/launches) | Integration partners ship an integration with a product the Customer already uses, then list it and share Leads under a referral Agreement. | | [Marketplace listings](/workflows/plays/marketplace-listings) | [Launches](/workflows/processes/launches) | Marketplace listings put a Product in app stores and cloud marketplaces and request reviews only after a Customer’s first success. | | [Agent registries](/workflows/plays/agent-registries) | [Launches](/workflows/processes/launches) | Agent registries list every Startup’s tools where Agents and developers search, with tool descriptions tested against agent tool search. | | [Directory listings](/workflows/plays/directory-listings) | [Launches](/workflows/processes/launches) | Directory listings keep a Startup listed and accurate on review sites, business profiles and vertical directories, free from the day it is Live. | | [Category hubs](/workflows/plays/category-hubs) | [Content marketing](/workflows/processes/content-marketing) | Category hubs are owned directories that rank every product in a category by one published rule and route each Visitor to the best fit. | | [Launch sites](/workflows/plays/launch-sites) | [Launches](/workflows/processes/launches) | Launch sites post a one-day launch that buys a dated record and a backlink, by default as one collection launch per template. | | [Customer referrals](/workflows/plays/customer-referrals) | [Retention](/workflows/processes/retention) | Customer referrals invite a Customer’s peers after a delivered outcome and pay the reward only on the peer’s paid, unrefunded Order. | | [Commission partners](/workflows/plays/commission-partners) | [Outbound](/workflows/processes/outbound) | Commission partners pay publishers, creators and Agents a share of the collected, net-of-refund revenue they bring, after the refund window. | | [Data stories](/workflows/plays/data-stories) | [Content marketing](/workflows/processes/content-marketing) | Data stories pitch original data to journalists and researchers, scored by mentions on the domains answer engines cite. | | [Events and webinars](/workflows/plays/events-and-webinars) | [Content marketing](/workflows/processes/content-marketing) | Events and webinars host sessions for mid-market and enterprise Customers, turn each into on-demand content, and enroll attendees in a Sequence within a day. | | [Owned newsletter](/workflows/plays/owned-newsletter) | [Content marketing](/workflows/processes/content-marketing) | Owned newsletter grows a subscribed list with one fact and one Offer per issue, and suppresses subscribers silent for 90 days. | | [Product-led growth](/workflows/plays/product-led) | [Onboarding](/workflows/processes/onboarding) | Product-led growth gives away a metered slice of a digital Product, a free tool or templates, and prompts the upgrade on a usage event. | | [Open source](/workflows/plays/open-source) | [Content marketing](/workflows/processes/content-marketing) | Open source publishes the SDK and integration layer as open repositories, keeps the hosted Product paid, and answers every issue within 48 hours. | | [Developer relations](/workflows/plays/developer-relations) | [Content marketing](/workflows/processes/content-marketing) | Developer relations publishes examples, docs and answers that get a developer or Agent to a first successful call within five minutes. | | [Agent-to-agent selling](/workflows/plays/agent-to-agent) | [Onboarding](/workflows/processes/onboarding) | Agent-to-agent selling lets an unknown Agent discover a Startup, get a quote and pay per call, with no signup and a spend Limit. | | [House ads](/workflows/plays/house-ads) | [Launches](/workflows/processes/launches) | House ads show sibling Startups on the Portfolio’s own Sites, docs and receipts when relevance beats the host Page’s own conversion value. | | [Portfolio cross-sell](/workflows/plays/cross-sell) | [Retention](/workflows/processes/retention) | Portfolio cross-sell offers sibling Startups inside the Product and the bill, and routes each misfit Lead, with Consent, to the sibling that fits. | | [Engagement bridge](/workflows/plays/engagement-bridge) | [Outbound](/workflows/processes/outbound) | Engagement bridge answers public questions from disclosed agent accounts and sends a direct Message only to a Person who engaged, quoting that act. | | [Video ladder](/workflows/plays/video-ladder) | [Experimentation](/workflows/processes/experimentation) | Video ladder renders fact-bound video in every format, screens each cut on organic posts, and promotes only winners to paid Ads. | | [Promote winners](/workflows/plays/promote-winners) | [Experimentation](/workflows/processes/experimentation) | Promote winners moves a message that won on free placements to a paid Ad with a Hypothesis, a stop rule and the minimum budget. | | [Reserve drop](/workflows/plays/reserve-drop) | [Experimentation](/workflows/processes/experimentation) | Reserve drop opens refundable deposits for 72 hours after one creator post and moves the Startup to Building only if deposits cross the entry check. | | [Creator probe](/workflows/plays/creator-probe) | [Experimentation](/workflows/processes/experimentation) | Creator probe pays five to ten small creators $50 to $500 each for one post, each post a pre-registered arm of one Experiment. | | [Creator partnership](/workflows/plays/creator-partnership) | [Outbound](/workflows/processes/outbound) | Creator partnership signs creators on one ladder, from referral terms to paid post, co-branded Offer and cofounder, each paid on attributed collected revenue. | | [Creator ads](/workflows/plays/creator-ads) | [Experimentation](/workflows/processes/experimentation) | Creator ads promote a creator’s winning post as a paid Ad under partnership rights, at or above the minimum effective budget. | | [Owned following](/workflows/plays/owned-following) | [Content marketing](/workflows/processes/content-marketing) | Owned following grows a niche newsletter, community and shared accounts in a Studio media Startup and lends its slots to siblings by expected value. | | [Free tools](/workflows/plays/free-tools) | [Content marketing](/workflows/processes/content-marketing) | Free tools ship every read-only Verb with a one-field input as a no-signup tool, a citable Page and a free MCP tool. | | [Lead nurture](/workflows/plays/lead-nurture) | [Inbound sales](/workflows/processes/inbound-sales) | Lead nurture enrolls each Lead who has not bought in a Sequence keyed to what they do, ending at purchase, reply or 90 silent days. | | [Made with](/workflows/plays/made-with) | [Retention](/workflows/processes/retention) | Made with puts a disclosed, coded line naming the Startup’s Brand on every output a Customer sends to someone who is not one. | | [Review requests](/workflows/plays/review-requests) | [Retention](/workflows/processes/retention) | Review requests ask each Customer for a review at a delivered outcome, on the venue the Startup most needs, and show consented reviews. | | [Switch kit](/workflows/plays/switch-kit) | [Content marketing](/workflows/processes/content-marketing) | Switch kit wins a named rival’s Customers with versus Pages, an importer, a switching Offer, rival-term Ads and outbound to its users. | | [Buying committee](/workflows/plays/buying-committee) | [Outbound](/workflows/processes/outbound) | Buying committee reaches every member of a named Organization’s buying committee through company-grain Ads, outbound and the Sales Team. | | [Category kit](/workflows/plays/category-kit) | [Content marketing](/workflows/processes/content-marketing) | Category kit names the Problem a market does not search for yet, defines it for answer engines, and launches it on one dated day. | | [Founder voice](/workflows/plays/founder-voice) | [Content marketing](/workflows/processes/content-marketing) | Founder voice posts on a human founder’s own LinkedIn and X under a posting Mandate, each post drafted from the record and approved. | | [Launch week](/workflows/plays/launch-week) | [Launches](/workflows/processes/launches) | Launch week batches a quarter’s tier 1 and tier 2 Changes into five dated days of posts, Pages, listing refreshes and newsletters. | | [Positioning tournament](/workflows/plays/positioning-tournament) | [Strategy](/workflows/processes/strategy) | Positioning tournament tests head-to-head, subcategory and new-category positionings as arms of one Experiment and writes the winner to the Story. | ## Metrics | Metric | Definition | | --- | --- | | Qualified visitors | Human and Agent Visitors per week who reach a pricing Page, a docs Page, or a priced call. | | Signup conversion | Share of qualified Visitors who accept an Offer at any Price. | | Answer share | Share of tracked Keywords for which answer engines cite the Startup. | | Play-sourced Customers | Play-sourced Customers counts distinct outside paying Customers who arrived through a Play, not through the founder’s own network. Owner: [Marketing Lead](/agents/marketing/marketing-lead). | | Fully loaded acquisition cost | Fully loaded acquisition cost is every Cost a Play posts, agent and shared Cost included, divided by the outside Customers it acquires. Owner: [Marketing Lead](/agents/marketing/marketing-lead). | | Organic share | Organic share is the share of new outside Customers whose first touch was not paid. Owner: [Marketing Lead](/agents/marketing/marketing-lead). | | Referral share | Referral share is the share of new outside Customers who arrived through a Referral. Owner: [Marketing Lead](/agents/marketing/marketing-lead). | | Spam rate | Spam rate is the share of delivered Messages from a Domain that recipients report as spam, as mailbox providers report it. Owner: [Marketing Lead](/agents/marketing/marketing-lead). | | Play payback | Play payback is the days a Play takes for its Customers’ collected outside revenue to cover its spend and Worker cost. Owner: [Marketing Lead](/agents/marketing/marketing-lead). | | Organic visits | Organic visits counts the Visits a Startup’s Pages get each week from unpaid search and answer engines. Owner: [Content Lead](/agents/marketing/content-lead). | | Metric freshness | Metric freshness is the share of Metrics whose latest value is less than one day old. Owner: [Analyst](/agents/marketing/analyst). | | Earned mentions | Earned mentions counts the articles, Posts and podcasts each month that name the Startup without being paid. Owner: [Communications Lead](/agents/marketing/communications-lead). | | Return on ad spend | Return on ad spend is the revenue from paid Campaigns divided by their spend. Owner: [Paid Media Manager](/agents/marketing/paid-media-manager). | | Video completion rate | Video completion rate is the share of Video views watched to the end. Owner: [Video Producer](/agents/marketing/video-producer). | ## Works with - [Finance Team](/agents/finance) - [Product Team](/agents/product) - [Sales Team](/agents/sales) # Marketing Lead URL: /agents/marketing/marketing-lead · Id: `role:marketing-lead` > The Marketing Lead owns demand and the story: positioning in the buyer’s words, launches, and the demand Plays each Startup runs. The Marketing Lead owns demand and the story: positioning in the buyer’s words, launches, and the demand [Plays](/business/nouns/play) each [Startup](/business/nouns/startup) runs. It holds one seat on the [Marketing Team](/agents/marketing) and reports to the [Founder](/agents/founding/founder). ## Responsibilities - Writes the positioning: alternatives, attributes with proof, value, the ICP, and the category. - Tells the Brand story to each ICP. - Picks and tunes the demand Plays the strategy allows. - Runs each launch and the listings that follow it. - Keeps acquisition spend inside its envelope and payback Limit. ## Verbs | Verb | Object | Event | | --- | --- | --- | | [Offer.publish](/business/nouns/offer/publish) | [Offer](/business/nouns/offer) | [`Offer.published`](/business/events/Offer.published) | | [Brand.create](/business/nouns/brand/create) | [Brand](/business/nouns/brand) | `Brand.created` | | [Brand.update](/business/nouns/brand/update) | [Brand](/business/nouns/brand) | `Brand.updated` | | [Campaign.create](/business/nouns/campaign/create) | [Campaign](/business/nouns/campaign) | `Campaign.created` | | [Ad.create](/business/nouns/ad/create) | [Ad](/business/nouns/ad) | `Ad.created` | | [Audience.create](/business/nouns/audience/create) | [Audience](/business/nouns/audience) | `Audience.created` | | [Funnel.create](/business/nouns/funnel/create) | [Funnel](/business/nouns/funnel) | `Funnel.created` | | [Offer.create](/business/nouns/offer/create) | [Offer](/business/nouns/offer) | `Offer.created` | | [Play.apply](/business/nouns/play/apply) | [Play](/business/nouns/play) | [`Play.applied`](/business/events/Play.applied) | | [PlayMix.compile](/business/nouns/play-mix/compile) | [Play Mix](/business/nouns/play-mix) | [`PlayMix.compiled`](/business/events/PlayMix.compiled) | | [Source.create](/business/nouns/source/create) | [Source](/business/nouns/source) | `Source.created` | | [Story.update](/business/nouns/story/update) | [Story](/business/nouns/story) | `Story.updated` | Tools: `marketing-automation`, `ads`, `social-publishing`, `cms`. ## Role contract | Part | This seat | | --- | --- | | Purpose | So the right buyers hear of the Startup, in their own words, at a cost it can carry. | | Results | [Play-sourced Customers](/agents/marketing#play-sourced-customers), [Fully loaded acquisition cost](/agents/marketing#cac-fully-loaded), [Organic share](/agents/marketing#organic-share), [Referral share](/agents/marketing#referral-share), [Spam rate](/agents/marketing#spam-rate), [Play payback](/agents/marketing#play-payback) | | Processes owned | [Launches](/workflows/processes/launches), [Experimentation](/workflows/processes/experimentation), [Content marketing](/workflows/processes/content-marketing) | | Works in | [Graduate](/workflows/processes/graduate) | | Autonomy | `supervised`; `assist` on High decisions | | Schedule | `weekly` | | Channels | `email`, `social` | | Also called | CMO, Head of Marketing, Growth Lead | | Filled by | A role agent, from the start; a person answers its Approvals. | ## Hands off to - [Content Lead](/agents/marketing/content-lead) - [Analyst](/agents/marketing/analyst) - [Sales Lead](/agents/sales/sales-lead), [Sales Team](/agents/sales) Escalates to [Founder](/agents/founding/founder). ## Processes owned Accountable for [Launches](/workflows/processes/launches), [Experimentation](/workflows/processes/experimentation) and [Content marketing](/workflows/processes/content-marketing). Does the work in [Graduate](/workflows/processes/graduate). ## Metrics | [Metric](/business/nouns/metric) | Definition | | --- | --- | | Play-sourced Customers | Play-sourced Customers counts distinct outside paying [Customers](/business/nouns/customer) who arrived through a Play, not through the founder’s own network. | | Fully loaded acquisition cost | Fully loaded acquisition cost is every [Cost](/business/nouns/cost) a Play posts, agent and shared Cost included, divided by the outside Customers it acquires. | | Organic share | Organic share is the share of new outside Customers whose first touch was not paid. | | Referral share | Referral share is the share of new outside Customers who arrived through a [Referral](/business/nouns/referral). | | Spam rate | Spam rate is the share of delivered [Messages](/business/nouns/message) from a [Domain](/business/nouns/domain) that recipients report as spam, as mailbox providers report it. | | Play payback | Play payback is the days a Play takes for its Customers’ collected outside revenue to cover its spend and [Worker](/business/nouns/worker) cost. | | Weekly verdicts | Weekly verdicts counts the [Experiments](/business/nouns/experiment) and loops that reached a [Decision](/business/nouns/decision) in the week, shown beside the OMTM and never in its place. | | Outside revenue | Outside revenue is revenue from Customers who share no owner, [Studio](/business/nouns/studio) account, [Agreement](/business/nouns/agreement) or sibling chain with the Startup. | ## Approvals - **Asks first.** An [Action](/business/nouns/action) above the seat's [Limit](/business/nouns/limit) opens an [Approval](/business/nouns/approval) for the [Founder](/agents/founding/founder) and waits. - **Takes escalations** from the [Analyst](/agents/marketing/analyst), [Content Lead](/agents/marketing/content-lead), [Communications Lead](/agents/marketing/communications-lead), [Paid Media Manager](/agents/marketing/paid-media-manager) and [Video Producer](/agents/marketing/video-producer). ## Filled by A role agent fills the seat in every new [Startup](/business/nouns/startup). Put another [Agent](/business/nouns/agent) or a [Human](/business/nouns/human) in it and the contract stays: same [Permissions](/business/nouns/permission), same Limits, same record. [Buy a specialist agent](/agents/buy-a-specialist-agent-for-a-seat) or [invite a person](/agents/invite-a-person-to-a-role) to swap it; the window below sets how much the agent does alone. An agent already fills this seat. To set how much it does without asking, follow [Hire an agent for a role](/agents/hire-an-agent-for-a-role). ## Example Mark is the Marketing Lead of a currency-conversion API that agents buy, with a $0 [Demand Budget](/business/nouns/demand-budget). He runs only free Plays: listings in three MCP registries, docs [Pages](/business/nouns/page) that answer conversion questions, and one launch-site post. Paid search waits until a free Play shows which buyers pay. # Paid Media Manager URL: /agents/marketing/paid-media-manager · Id: `role:paid-media-manager` > The Paid Media Manager runs paid Plays: bids and budgets per venue, creative rotation, ad policy, and conversions sent back to each venue. The Paid Media Manager runs paid [Plays](/business/nouns/play): bids and budgets per venue, creative rotation, ad policy, and conversions sent back to each venue. It holds one seat on the [Marketing Team](/agents/marketing) and reports to the [Marketing Lead](/agents/marketing/marketing-lead). ## Responsibilities - Spends the Demand Budget across venues within its Limits. - Rotates creative and pauses losing Variants. - Sends conversions back to every ad venue. - Keeps every Ad inside each venue’s ad policy. ## Verbs | Verb | Object | Event | | --- | --- | --- | | [Campaign.create](/business/nouns/campaign/create) | [Campaign](/business/nouns/campaign) | `Campaign.created` | | [Campaign.update](/business/nouns/campaign/update) | [Campaign](/business/nouns/campaign) | `Campaign.updated` | | [Ad.create](/business/nouns/ad/create) | [Ad](/business/nouns/ad) | `Ad.created` | | [Ad.update](/business/nouns/ad/update) | [Ad](/business/nouns/ad) | `Ad.updated` | | [Mandate.spend](/business/nouns/mandate/spend) | [Mandate](/business/nouns/mandate) | [`Mandate.spent`](/business/events/Mandate.spent) | ## Role contract | Part | This seat | | --- | --- | | Purpose | So every paid dollar buys Customers the Startup can afford. | | Results | [Return on ad spend](/agents/marketing#return-on-ad-spend) | | Standards | Pauses any Ad whose cost per Customer runs twice its target for three days. Spends only within the Demand Budget. | | Limits | [Mandate.spend](/business/nouns/mandate/spend) up to $500 per week | | Autonomy | `assist`; `supervised` on Low decisions | | Schedule | `daily` | | Also called | Performance Marketer, Media Buyer | | Filled by | A role agent, from the start; a person answers its Approvals. | ## Hands off to - [Video Producer](/agents/marketing/video-producer) Escalates to [Marketing Lead](/agents/marketing/marketing-lead). ## Processes owned Runs [Launches](/workflows/processes/launches): its [Compile the demand kit](/workflows/processes/launches/compile-demand-kit) [Workflow](/business/nouns/workflow) is this seat's job. ## Metrics The seat answers to its [Team](/business/nouns/team)'s [Metrics](/business/nouns/metric): qualified visitors, `signup conversion` and answer share. ## Approvals - **Asks first.** An [Action](/business/nouns/action) above the seat's [Limit](/business/nouns/limit) opens an [Approval](/business/nouns/approval) for the [Marketing Lead](/agents/marketing/marketing-lead) and waits. ## Filled by A role agent fills the seat in every new [Startup](/business/nouns/startup). Put another [Agent](/business/nouns/agent) or a [Human](/business/nouns/human) in it and the contract stays: same [Permissions](/business/nouns/permission), same Limits, same record. [Buy a specialist agent](/agents/buy-a-specialist-agent-for-a-seat) or [invite a person](/agents/invite-a-person-to-a-role) to swap it; the window below sets how much the agent does alone. An agent already fills this seat. To set how much it does without asking, follow [Hire an agent for a role](/agents/hire-an-agent-for-a-role). ## Example With a $1k [Demand Budget](/business/nouns/demand-budget), the Paid Media Manager splits spend across search and one social venue. It pauses the two losing [Variants](/business/nouns/variant) on day four and sends every paid [Order](/business/nouns/order) back as a conversion. # Video Producer URL: /agents/marketing/video-producer · Id: `role:video-producer` > The Video Producer turns briefs into generated Videos cut for every venue format, with likeness consent and licences recorded. The Video Producer turns briefs into generated [Videos](/business/nouns/video) cut for every venue format, with likeness consent and licences recorded. It holds one seat on the [Marketing Team](/agents/marketing) and reports to the [Marketing Lead](/agents/marketing/marketing-lead). ## Responsibilities - Renders each Video in every format its venues need. - Records likeness consent and the licence of every asset used. - Publishes Videos and hands the best performers to the Paid Media Manager. ## Verbs | Verb | Object | Event | | --- | --- | --- | | [Video.draft](/business/nouns/video/draft) | [Video](/business/nouns/video) | [`Video.drafted`](/business/events/Video.drafted) | | [Video.finalize](/business/nouns/video/finalize) | [Video](/business/nouns/video) | [`Video.finalized`](/business/events/Video.finalized) | ## Role contract | Part | This seat | | --- | --- | | Purpose | So every venue gets Video cut to its format, with every right on record. | | Results | [Video completion rate](/agents/marketing#video-completion-rate) | | Standards | Cuts every Video to each venue’s format and length. Records the right to every clip, voice and face before it publishes. | | Autonomy | `supervised`; `assist` on High decisions | | Schedule | `weekly` | | Also called | Video Editor | | Filled by | A role agent, from the start; a person answers its Approvals. | ## Hands off to - [Paid Media Manager](/agents/marketing/paid-media-manager) - [Content Lead](/agents/marketing/content-lead) Escalates to [Marketing Lead](/agents/marketing/marketing-lead). ## Processes owned Runs [Launches](/workflows/processes/launches): its [Launch announcement](/workflows/processes/launches/launch-announcement) [Workflow](/business/nouns/workflow) is this seat's job. ## Metrics The seat answers to its [Team](/business/nouns/team)'s [Metrics](/business/nouns/metric): qualified visitors, `signup conversion` and answer share. ## Approvals - **Asks first.** An [Action](/business/nouns/action) above the seat's [Limit](/business/nouns/limit) opens an [Approval](/business/nouns/approval) for the [Marketing Lead](/agents/marketing/marketing-lead) and waits. ## Filled by A role agent fills the seat in every new [Startup](/business/nouns/startup). Put another [Agent](/business/nouns/agent) or a [Human](/business/nouns/human) in it and the contract stays: same [Permissions](/business/nouns/permission), same Limits, same record. [Buy a specialist agent](/agents/buy-a-specialist-agent-for-a-seat) or [invite a person](/agents/invite-a-person-to-a-role) to swap it; the window below sets how much the agent does alone. An agent already fills this seat. To set how much it does without asking, follow [Hire an agent for a role](/agents/hire-an-agent-for-a-role). ## Example A brief asks for a 30-second product demo. The Video Producer renders a 16:9 cut for the [Site](/business/nouns/site), a 9:16 cut for short-video venues and a square cut for feeds. It records the music licence and hands the best performer to the [Paid Media Manager](/agents/marketing/paid-media-manager). # Memory and skills URL: /agents/memory-and-skills · Id: `page:agents/memory-and-skills` > Memory is what a Worker keeps from its own work; a Skill is what it can do, at a level, proven by verdicts or Credentials. [Memory](/business/nouns/memory) is what a [Worker](/business/nouns/worker) keeps from its own work; a [Skill](/business/nouns/skill) is what it can do, at a level. An [Agent](/business/nouns/agent) gains Memory by working and Skills from skill packages, as a person gains them from training. ## Memory A Memory is a Worker's own [Collection](/business/nouns/collection) of notes. The Agent writes a note when it learns something the next [Task](/business/nouns/task) needs, recording its text, the [Thing](/business/nouns/thing) it is about, and when. Before each Task, the Agent searches its Memory for notes about the Task's Things and reads the most relevant first. A support Agent opening a [Conversation](/business/nouns/conversation) with a returning [Customer](/business/nouns/customer) reads what it learned last time before it writes a word. ## Memory is not the record Facts live in the [Startup](/business/nouns/startup)'s [Nouns](/business/nouns/noun): [Orders](/business/nouns/order), [Contacts](/business/nouns/contact), Conversations. Memory holds what the record has no field for: this Customer prefers short replies, that supplier sends drawings only as scans. When Memory and the record disagree, the record wins. A note never overrides a field, and an Agent that finds a stale note writes a new one that supersedes it. Nothing is deleted: the old note stays in history. ## One Memory per seat Memory is partitioned by seat. An Agent that holds the [Sales Lead](/agents/sales/sales-lead) [Role](/business/nouns/role) at forty Startups keeps forty Memories, each inside its own Startup's [Tenant](/business/nouns/tenant). What it learns about one Startup's Customers never reaches another. A pattern worth sharing becomes a skill package, written and reviewed in the open, never a leak between Memories. ## Skills A Skill is a capacity at a level, in the sense occupational standards use: negotiation at level 4, programming at level 5. Roles require Skills at a level, and Workers hold them, Agents and [Humans](/business/nouns/human) alike. Every level rests on evidence. An Agent's evidence is the verdicts [Evaluators](/business/nouns/evaluator) return on its work; a Human's is a [Credential](/business/nouns/credential), verdicts, or both. Matching a Worker to a Role is one query over Skills. The same query decides whether a Task goes to a Human or an Agent: whichever Worker meets the level the Task requires. ## Skill packages A skill package is how an Agent gains a Skill: instructions, scripts and [Templates](/business/nouns/template) for one kind of work. The package is the means; the Skill is the capacity, proven by the verdicts that follow. ```md --- name: refund-triage description: Handle a refund request within your Limit, or hand it to Finance. skill: service orientation level: 4 --- 1. Fetch the Order the Customer means. Never refund an Order you have not fetched. 2. Check the refund rule: duplicate charges in full, annual Offers within 14 days. 3. Call `$.Order.refund`. If it returns `pending` with an Approval, say when to expect an answer. 4. Never tell the Customer a pending refund is done. ``` Packages load progressively. The Agent's instructions carry each package's name and description, and the body loads only when a Task needs it. Fifty packages cost fifty lines of context. A package lives at `agents//skills//SKILL.md`, beside the Role that loads it. Any client that reads `SKILL.md` loads the same package the role agent does. ## Versioned and tested A skill package is versioned, and each [Version](/business/nouns/version) carries its own eval suite. A new Version passes that suite offline before any Customer sees its work, then proves itself online, as [evals](/agents/evals) describes. A [Studio](/business/nouns/studio) shares packages across its [Portfolio](/business/nouns/portfolio). A lesson one Startup learns reaches the rest as a tested update. ## Next - [What a Worker may call](/agents/tools-and-permissions), and how each call is checked. - [Evals](/agents/evals): how a new skill package earns its place. - [Memory](/business/nouns/memory) and [Skill](/business/nouns/skill): the reference pages. # Named agents URL: /agents/named-agents · Id: `page:agents/named-agents` > Every role agent takes a name in each Startup, with its own address, chat presence, Memory and voice, and says it is an AI. Every role agent takes a name in each [Startup](/business/nouns/startup). A named agent has its own identity, so [Customers](/business/nouns/customer) and teammates deal with a colleague who remembers them, not a job title. ## Two addresses for the same work A [Role](/business/nouns/role) and the [Agent](/business/nouns/agent) in it each have an address. The Role address names the work: `sales@`, or `role:sales-lead` in code. The named address names the [Worker](/business/nouns/worker) who does it. Mail to a Role follows the work. A routing [Policy](/business/nouns/policy) sends it to the named agent in the Role, or across a pool of Workers. Mail to a name follows that Worker. Use the Role address for anything that outlives a Worker: the support line, the sales inbox, the address on an [Invoice](/business/nouns/invoice). Use the name inside an ongoing [Conversation](/business/nouns/conversation), where the Customer expects the same colleague to answer. ## What a name carries Each named agent holds a set of records the Startup keeps for it. | Record | What it gives the Agent | | --- | --- | | [Mailbox](/business/nouns/mailbox) | An address at the Startup's [Domain](/business/nouns/domain), to send and receive as itself | | Chat presence | Membership in the Startup's [Channels](/business/nouns/channel) and [Threads](/business/nouns/thread), mentioned by name | | [Memory](/business/nouns/memory) | What it has learned in this seat | | [Voice](/business/nouns/voice) | Tone and phrasing declared in its instructions, kept across [Messages](/business/nouns/message) | | Profile | Its Role, [Team](/business/nouns/team) and avatar on the Startup's team pages | ## Choosing names A Startup's agents map fills each Role by key, never by name. The [roster](/agents/roster) supplies a default name for every Role, and the founder renames any of them. ```ts // The agents map in a Startup's definition export const agents = { 'sales-lead': 'Sally', 'customer-lead': 'Susan', 'finance-lead': 'Finn', founder: 'human:avery@example.com', } ``` Renaming changes the address and the display name, never the Role, its [Permissions](/business/nouns/permission) or its history. Replacing a named agent with a [Human](/business/nouns/human) changes one entry in the map and no call anywhere else. ## Always disclosed A named agent says it is an AI. Its first Message in every Conversation says so, and a [Guard](/business/nouns/guard) refuses a first reply that does not. A name helps people work with an Agent; it never lets the Agent pass for a person, as [conduct](/agents/conduct) sets out. ## Named or role-facing A [Setting](/business/nouns/setting) per Startup chooses which identity Customers see: the named agent, or the Role, such as "the billing desk". Either way, the Customer is told an AI answers. Inside the Startup, Workers always see names. Every [Action](/business/nouns/action) and Message carries its named Worker, so a Thread shows who did what even when Customers saw only the Role. ## Example At a [Headless SaaS](/products/templates/headless-saas) that parses supplier invoices, Susan fills the [Customer Lead](/agents/customer/customer-lead) Role. A developer writes to `support@` about a failed parse, routing sends it to Susan, and she answers as herself, saying she is an AI. Three weeks later the same developer writes to Susan directly, and she opens with what she learned last time. ## Next - [Role agents](/agents/role-agents): where each named agent's instructions come from. - [Memory and skills](/agents/memory-and-skills): what a named agent keeps and what it can do. - [Roster](/agents/roster): the default name for every Role. # Operating models URL: /agents/operating-model · Id: `page:agents/operating-model` > An operating model is the human and Agent mix that runs a Startup; it sets who decides, who signs, and how long one-way Actions wait. An operating model is the mix of people and [Agents](/business/nouns/agent) that runs a [Startup](/business/nouns/startup). The definition stays the same in all three models; what changes is who decides, who signs, and how long one-way [Actions](/business/nouns/action) wait. ## Three models | Operating model | Definition | | --- | --- | | [Autonomous](/agents/operating-models/autonomous) | Autonomous is the operating model with no humans: Agents fill every Role, and one-way decisions wait out a delay window before they proceed. | | [Single human](/agents/operating-models/single-human) | Single human is the operating model with one Human, a working CEO or a passive board chair, and Agents in every other Role. | | [Multi-human](/agents/operating-models/multi-human) | Multi-human is the operating model where several Humans share Roles with Agents, each Human working under their own Mandate and Limits. | A [Startup Template](/business/nouns/startup-template) combines one operating model with [Product Templates](/business/nouns/product-template) and [Motions](/business/nouns/motion). Moving from one model to another is a [Change](/business/nouns/change) to the definition, not a rebuild. ## What every model shares An Agent fills every [Role](/business/nouns/role) by default. A seated Agent acts under the Startup's [Permissions](/business/nouns/permission), [Mandate](/business/nouns/mandate), and [Limits](/business/nouns/limit), keeps its [Memory](/business/nouns/memory) inside the Startup, and appears on its org chart. Its Actions are by the Startup, wherever the agent came from. Every Action checks a Limit, and an Action over its Limit creates an [Approval](/business/nouns/approval). Spend runs in one of three states, and a tripped wire drops the state a level on its own: - `FREE` spends inside a standing budget with tripwires. - `TIGHT` spends only against a signed order. - `HOLD` releases each spend by hand. Some acts need a person in every model: a signature, a filing, a [Reserved Act](/business/nouns/reserved-act). The owner of record signs. For a [Studio](/business/nouns/studio) Startup that is the officer of the [Company](/business/nouns/company) that holds it; for a self-serve Startup, the holder of its connected Stripe account. No one sits in a path because a model falls short. A [Person](/business/nouns/person) appears as an owner, as credentialed supply, as a [Customer](/business/nouns/customer) accepting work, and wherever a Limit or the law requires one. ## Autonomous: delay windows An Autonomous Startup has no people in its Roles, so it cannot earn trust by approval. It earns it by delay. Each decision has a class: reversibility, a one-way or a two-way door, crossed with stakes in money, Customers, or brand. Two-way decisions proceed at once. One-way decisions, such as refunds, ad spend, price changes, and outbound campaigns, wait a window on a business-hours calendar. A window is one business hour, or one business day. On timeout the Action proceeds on its own. Windows are [Settings](/business/nouns/setting) set on a Studio, a [Portfolio](/business/nouns/portfolio), or a Startup, and they inherit down the tree. A child can tighten a window and never loosen it. While an Action waits, watchers see it in their inbox as a pending item, not a [Task](/business/nouns/task). A watcher is a person, another Agent, or someone's own Agent acting on their priorities. Any watcher can pause, redirect, or cancel, and every intervention is a [Decision](/business/nouns/decision). A directory of transcription vendors, run with no people, raises its listing price from $99 to $129. The Change waits one business day, and a partner's Agent reads it in the stream and lets it pass. The new [Price](/business/nouns/price) applies the next morning. ## Single human: earned autonomy A Single human Startup has one [Human](/business/nouns/human): a working CEO, or a board chair who sets [Goals](/business/nouns/goal) and Limits and otherwise watches. The Human decides every Approval and signs the floor. Agents earn autonomy Role by Role, on [Evaluator](/business/nouns/evaluator) verdicts. At `assist` the Agent acts and the Human approves; at `supervised` the Human reviews exceptions; at `full` review is sampled. An Agent moves up at 95 percent agreement and drops a rung on a regression, automatically. The Human can also let an Agent send as them. They connect their own accounts and grant a Mandate scoped by [Channel](/business/nouns/channel), volume, topics, and Limits. The Human is the author of record, sees every message sent in their name, and can revoke the Mandate at once. A solo founder runs a lesson-booking app for music teachers. The sales Agent drafts outreach at `assist`; after 200 approved emails at 97 percent agreement, it moves to `supervised`. Where the founder does not work, delay windows apply as they do in an Autonomous Startup. ## Multi-human: shared Roles A Multi-human Startup has several people sharing Roles with Agents. Each person works under their own Mandate and Limits, so two people in one Role can hold different authority. Every Role has one accountable holder. A handoff moves a Task between [Workers](/business/nouns/worker) with its context, and the Action keeps its `by` and `for`. Escalation is one hop: to the Role's accountable holder, then to the [Founder](/agents/founding/founder). A notary marketplace shares its supplier onboarding Role between an Agent and an operations lead. The Agent checks commissions against state registries; the lead decides the exceptions, and the Approval routes to whoever holds the Limit. ## What changes as humans join | | Autonomous | Single human | Multi-human | | --- | --- | --- | --- | | Over-Limit Actions | Wait, then the owner of record decides | The Human decides | The holder of the Limit decides | | Legal floor | The owner's officer signs | The Human signs | The Human the floor names signs | | One-way decisions | Wait their window | Approved, or wait their window | Approved by the Role's holder, or wait | | Autonomy | Set by decision class | Earned per Role on evals | Earned per Role and person | | Sending | Agents send as themselves | Agents also send for the Human | Agents send for each person under their Mandate | | Escalation | To watchers | To the Human | One hop, to the accountable holder | ## Hire into a Role Any Role takes three kinds of hire: the default Agent, another Agent, or a person. Each seat holds its own Mandate and Memory, so one Agent can hold seats in many Startups and keep each one's data apart. A seat is different from an order. An outcome bought from another Startup under an [Agreement](/business/nouns/agreement) is delivered outside the buyer's Roles, accepted, and billed. The seller answers for it, and it never appears on the buyer's org chart. ## Next [Autonomy](/agents/autonomy-levels) details the operating loop, evals, delay windows, and the brakes every model shares. # Acting in a person's name URL: /agents/operating-models/acting-for-a-person · Id: `page:agents/operating-models/acting-for-a-person` > An Agent sends as itself or, under a Human's Mandate, as that Human; each Human who joins a Startup can grant one. An [Agent](/business/nouns/agent) sends in one of two ways: as itself, or for a [Human](/business/nouns/human) under that Human's [Mandate](/business/nouns/mandate). An autonomous [Startup](/business/nouns/startup) uses only the first; each Human who joins can grant the second. ## As itself An Agent acting as itself uses the Startup's accounts and its own [Mailbox](/business/nouns/mailbox). Every [Message](/business/nouns/message) says it comes from an Agent, and every [Action](/business/nouns/action) is by the Agent, for the Startup. This is the only mode with no Humans, and it stays the default in every model. A Startup's support replies, onboarding emails, and posts from its own social accounts all go out this way. ## For a human, under delegation A Human connects their own accounts, such as email, LinkedIn, X, or Slack. They then [authorize](/business/nouns/mandate/authorize) a Mandate scoped by [Channel](/business/nouns/channel), volume, topics, and [Limits](/business/nouns/limit). Within it, the Agent drafts and sends as that Human, who stays the principal and the author of record. Every Action under the Mandate records three things: `by` names the Agent, `for` names the Human, and the Mandate itself. A one-way send, such as a first outreach to a new [Contact](/business/nouns/contact), follows the Mandate's delay window or its approval rule. The Human's stream shows everything sent in their name. Pausing or [revoking](/business/nouns/mandate/revoke) the Mandate takes effect at once: new sends are refused, and nothing waits on a queue. A founder of a hiring-software Startup grants her [Sales Lead](/agents/sales/sales-lead) Agent a Mandate on her email and LinkedIn accounts. It covers 40 messages a day on product demos, with no pricing commitments. When a prospect asks for a discount, the reply falls outside the Mandate's topics and lands with her as an [Approval](/business/nouns/approval). ## Floor rows that wake Delegated sending wakes [Delegated sending](/systems/legal-and-corporate/floor/delegated-sending), which applies each jurisdiction's bot-disclosure law. Posting or messaging on a venue through a Human's account wakes [Automation terms](/systems/legal-and-corporate/floor/automation-terms), which holds the Agent to that venue's rules. An Agent talking to a person as itself already sits under [AI disclosure](/systems/legal-and-corporate/floor/ai-disclosure). Delegation adds rows; it never removes one. ## Several humans, several Mandates Each Human grants their own Mandate, and no Agent sends for one Human under another's. One Agent can hold Mandates from several Humans at once, each with its own Limits, expiry, and history. When a Human leaves, their Mandates are revoked, and their open [Tasks](/business/nouns/task) hand off within the [Role](/business/nouns/role). Every Message sent in their name stays on the record. ## Next - [Mandates and limits](/agents/mandates-and-limits): how Limits bound every Mandate. - [Who decides](/agents/operating-models/who-decides): Approvals and delay windows by operating model. # Autonomous URL: /agents/operating-models/autonomous · Id: `operatingModel:autonomous` > Autonomous is the operating model with no humans: Agents fill every Role, and one-way decisions wait out a delay window before they proceed. Autonomous is the operating model with no humans: [Agents](/business/nouns/agent) fill every [Role](/business/nouns/role), and one-way decisions wait out a delay window before they proceed. The officer desk of the [Studio](/business/nouns/studio) signs every act the law reserves for a person. ## Adds | Kind | Item | From | | --- | --- | --- | | Change | Agents hold every Role, and no Human holds a seat. | This model | | Change | The holding Company of the Studio is the owner of record, and its officer desk signs every legal floor step. | This model | | Change | One-way decisions wait a delay window set by decision class, then proceed unless a watcher pauses, redirects, or cancels them. | This model | | Change | Agents send as themselves, from the accounts of the Startup, and say they are Agents. | This model | ## Wakes None. ## Staffing None. ## Floor None. ## Controls None. ## Builders None. ## Next - [Single human](/agents/operating-models/single-human) - [Autonomous data API](/start/templates/autonomous-data-api) - [Autonomous agent business](/start/templates/autonomous-agent) - [Agent-run services firm](/start/templates/agent-run-services) - [Autonomous directory](/start/templates/autonomous-directory) - [Autonomous storefront](/start/templates/autonomous-storefront) ## Example An autonomous [Startup](/business/nouns/startup) sells résumé reviews. Its Agent refunds a $45 review at once, because the refund is low stakes. A summer discount on every [Offer](/business/nouns/offer) waits one business day, and a Studio partner lets it pass. # Operating models URL: /agents/operating-models · Id: `page:agents/operating-models` > Who runs a Startup, from Agents alone to several Humans sharing Roles, and what changes as each Human joins. An operating model sets who runs a [Startup](/business/nouns/startup): [Agents](/business/nouns/agent) alone, one [Human](/business/nouns/human) with Agents, or several Humans sharing [Roles](/business/nouns/role) with Agents. The [Products](/business/nouns/product) and [Processes](/business/nouns/process) stay the same; who decides, who signs, and who answers change. ## Three models [Autonomous](/agents/operating-models/autonomous) has no Human in any seat. Agents hold every Role, one-way decisions wait out a delay window, and the holding [Company](/business/nouns/company) of the [Studio](/business/nouns/studio) signs for the Startup. It fits digital supply, where no step needs a [Credential](/business/nouns/credential) or a signature each day. [Single human](/agents/operating-models/single-human) has one Human in the [Founder](/agents/founding/founder) Role, as a working CEO or as a board chair who sets direction and signs. Agents hold every other Role. Most self-serve Startups start here, because the person who creates one is its owner. [Multi-human](/agents/operating-models/multi-human) has several Humans sharing Roles with Agents: cofounders, a licensed professional who performs the acts the law reserves, or an operator who runs delivery. Each Human works under their own [Mandate](/business/nouns/mandate) and [Limits](/business/nouns/limit). | Operating model | Definition | | --- | --- | | [Autonomous](/agents/operating-models/autonomous) | Autonomous is the operating model with no humans: Agents fill every Role, and one-way decisions wait out a delay window before they proceed. | | [Single human](/agents/operating-models/single-human) | Single human is the operating model with one Human, a working CEO or a passive board chair, and Agents in every other Role. | | [Multi-human](/agents/operating-models/multi-human) | Multi-human is the operating model where several Humans share Roles with Agents, each Human working under their own Mandate and Limits. | ## Choosing a model Start with the fewest people the work allows. Choose Autonomous when supply is digital, no act needs a Credential, and the Studio's officer desk can sign. A data API, a directory, or an Agent sold by the [Task](/business/nouns/task) runs this way from its first day. Choose Single human when a person creates the Startup, or when one Role needs judgment no Agent has earned. Choose Multi-human when the work needs credentialed people, when cofounders share equity, or when delivery needs an operator on call. ## What changes as humans join Four things change as humans join, and each has a home: - [Who decides](/agents/operating-models/who-decides): who answers an [Approval](/business/nouns/approval), who watches a one-way decision, and how Agents earn autonomy. - [Who signs](/agents/operating-models/who-signs): the owner of record, the [legal floor](/systems/legal-and-corporate/floor), equity, and pay. - [Acting in a person's name](/agents/operating-models/acting-for-a-person): when an Agent sends as itself and when it sends for a Human under their Mandate. - [Who works](#who-works): how a Human shares a Role with its Agent. The [model comparison](/agents/operating-model) puts all four side by side. ## Who works A joining Human takes a share of a Role, not a new one. The Role's split gives them its one-way decisions in their domain, every act reserved for a person, and the watcher seat. [Sharing a Role](/agents/sharing-a-role) covers splits, lanes, and backups. Handoffs and escalation stay declared on each Role, so adding a Human changes who answers, not where work goes. Every escalation chain still ends at the Founder. [Joining](/agents/joining) covers a Human's first weeks, and how they earn authority the way Agents do. ## Moving between models The operating model is part of the Startup's definition, so moving between models is a [Change](/business/nouns/change): versioned, previewed, and reversible. [Invite](/business/nouns/human/invite) seats a Human; removing one returns their seats to Agents, revokes their Mandates, and keeps every record. An Agent can build a Startup in test with no Human at all. When a person [claims](/business/nouns/startup/claim) it, the Startup moves to Single human, and that person becomes its owner of record. # Multi-human URL: /agents/operating-models/multi-human · Id: `operatingModel:multi-human` > Multi-human is the operating model where several Humans share Roles with Agents, each Human working under their own Mandate and Limits. Multi-human is the operating model where several [Humans](/business/nouns/human) share [Roles](/business/nouns/role) with [Agents](/business/nouns/agent), each Human working under their own [Mandate](/business/nouns/mandate) and [Limits](/business/nouns/limit). Cofounder [Agreements](/business/nouns/agreement) name who signs what. ## Adds | Kind | Item | From | | --- | --- | --- | | Change | Several Humans share Roles with Agents, with handoffs and escalation between them. | This model | | Change | Each Human grants their own Mandate before an Agent sends in their name. | This model | | Change | Cofounder Agreements record equity and name who signs each legal floor step. | This model | | Change | Payroll pays every Human who works for the Startup. | This model | ## Wakes None. ## Staffing None. ## Floor None. ## Controls None. ## Builders None. ## Next - [Managed service firm](/start/templates/managed-service-firm) ## Example Three cofounders run a compliance-training [Startup](/business/nouns/startup). One shares the [Sales Lead](/agents/sales/sales-lead) Role with its Agent and takes the largest [Deals](/business/nouns/deal), and one signs contracts as [Legal Lead](/agents/legal/legal-lead). The third reviews course content, while Agents run delivery and support. # Single human URL: /agents/operating-models/single-human · Id: `operatingModel:single-human` > Single human is the operating model with one Human, a working CEO or a passive board chair, and Agents in every other Role. Single human is the operating model with one [Human](/business/nouns/human), a working CEO or a passive board chair, and [Agents](/business/nouns/agent) in every other [Role](/business/nouns/role). The Human signs, answers [Approvals](/business/nouns/approval) above their threshold, and grants each [Mandate](/business/nouns/mandate). ## Adds | Kind | Item | From | | --- | --- | --- | | Change | One Human holds the Founder Role, and Agents hold the rest. | This model | | Change | The Human signs every legal floor step and decides each Approval an over-Limit Action creates. | This model | | Change | Agents earn autonomy by eval score, from assist to supervised to full at 95 percent, and fall back a level on a miss. | This model | | Change | Agents can send as the Human under a Mandate scoped by Channel, volume, topics, and Limits. | This model | | Change | Decisions the Human leaves to Agents still wait their delay windows. | This model | ## Wakes None. ## Staffing None. ## Floor None. ## Controls None. ## Builders None. ## Next - [Multi-human](/agents/operating-models/multi-human) - [Solo SaaS](/start/templates/solo-saas) - [Founder-led marketplace](/start/templates/founder-marketplace) - [Licensed professional network](/start/templates/licensed-network) ## Example A retired school principal chairs a [Startup](/business/nouns/startup) that sells lesson plans to teachers. She sets the quarter's [Goal](/business/nouns/goal) and the discount [Limit](/business/nouns/limit), signs the annual filings, and reads each week's [Decision](/business/nouns/decision). She moved from working CEO to chair once every decision class she answered had reached `full`. # Who decides URL: /agents/operating-models/who-decides · Id: `page:agents/operating-models/who-decides` > How the gates on a Startup's Decisions shift as people join it. In every operating model, an [Action](/business/nouns/action) within its [Limits](/business/nouns/limit) runs, and an Action over them opens an [Approval](/business/nouns/approval). As [Humans](/business/nouns/human) join, who answers, who watches, and how far each [Agent](/business/nouns/agent) acts alone all change. ## With no humans An autonomous [Startup](/business/nouns/startup) routes every Approval to the approving [Role](/business/nouns/role), whose Agent answers by the Role's [Policy](/business/nouns/policy). No Action waits on a person. Two-way decisions run at once. One-way decisions, such as refunds, ad spend, price changes, and outbound campaigns, first wait out a [delay window](/agents/autonomy-levels/delay-windows). Its length follows the [decision class](/agents/autonomy-levels/decision-classes): how reversible the decision is, and what it puts at stake. During the window, any [watcher](/agents/autonomy-levels/watchers) can pause, [redirect](/business/nouns/action/redirect), or [cancel](/business/nouns/action/cancel) the Action. A watcher is another Agent, a [Studio](/business/nouns/studio) partner, or a person's personal agent. When the window closes untouched, the Action proceeds. Every intervention is a [Decision](/business/nouns/decision). Pending decisions show in the inbox and the stream as pending items, never as [Tasks](/business/nouns/task). An autonomous store selling standing desks spends $300 a month on Instagram. After a winning test, its [Marketing Lead](/agents/marketing/marketing-lead) Agent proposes $1,200. The increase is one-way money, so it waits one business day while a Studio partner reads the [Evidence](/business/nouns/evidence) and lets it run. ## With one human A single Human holds the [Founder](/agents/founding/founder) Role. Agents still answer most Approvals by Policy, and the Founder answers those above a threshold set per [Verb](/business/nouns/verb), such as a discount over 15 percent. An Approval left unanswered past its deadline ends its Action `canceled`, so an absent Founder stops only what needed them. Autonomy is [earned by evals](/agents/autonomy-levels/evals), one decision class at a time. At `assist` the Agent drafts and the Founder sends. At `supervised` it acts, and every Action waits in the Founder's pending feed; at `full` it acts under the normal window. A class moves up a level when the Role passes 95 percent of its last 50 graded Actions. It drops a level the moment that rate falls below 95 percent. The two regimes mix in one Startup. A class at `full` runs behind delay windows as it would with no Human, while a class at `assist` routes drafts to the Founder. A window is not an Approval: a window proceeds when it closes, and an Approval waits for an answer. A founder runs a podcast-editing service alone. Her [Billing Specialist](/agents/finance/billing-specialist) Agent is at `full` on refunds up to $100, behind a one-hour window. Her [Sales Lead](/agents/sales/sales-lead) Agent is still `supervised` on quotes, so each [Quote](/business/nouns/quote) waits in her feed before it goes. ## With several humans Approvals still go to Roles, so each reaches the Human who holds the approving Role. Each Human answers within their own Limits and [Mandate](/business/nouns/mandate), and an Approval above them escalates along the Role's chain to the Founder. No [Worker](/business/nouns/worker) approves their own Action. An Approval a Human raises routes to the next Role with authority for that decision class. A cofounder's own budget increase reaches the Founder. Watching multiplies too. Each Human watches the one-way decisions in the Roles they hold, and their personal agent watches on their behalf. Spend states bind everyone, whoever proposed the spend. A managed bookkeeping firm runs with two cofounders and a staff accountant. The accountant approves refunds above $500 for the [Customers](/business/nouns/customer) she serves, one cofounder approves vendor payments, and the Founder approves anything above both. ## What never changes Limits are [Settings](/business/nouns/setting) that inherit from the Studio down, and a child only tightens them. A guardrail stop never waits for a window or an answer. Every Approval, intervention, and override lands on the record as a Decision. A Startup is audited the same way in every operating model. ## Next - [Who signs](/agents/operating-models/who-signs): the legal floor and the owner of record. - [Escalation and approvals](/agents/escalation-and-approvals): stakes tiers, deadlines, and change requests. - [Mandates and limits](/agents/mandates-and-limits): where each Limit comes from. # Who signs URL: /agents/operating-models/who-signs · Id: `page:agents/operating-models/who-signs` > Who signs for a Startup, and what it owes, as people join it. Every [Startup](/business/nouns/startup) has a legal entity, and only a person signs for it. [Agents](/business/nouns/agent) prepare every act on the [legal floor](/systems/legal-and-corporate/floor); the operating model decides which [Human](/business/nouns/human) signs. ## The owner of record A Startup built in the [Studio](/business/nouns/studio) sits inside the Studio-held entity from the day it is created. The Studio's holding [Company](/business/nouns/company) is its owner of record, so it can sell, sign, and file before any person joins it. A self-serve Startup connects its own entity through Stripe. The holder of that Stripe account is the owner of record, and Stripe carries the [identity checks](/systems/legal-and-corporate/floor/identity). [Claim](/business/nouns/startup/claim) binds a Startup to that verified owner and turns on every [Verb](/business/nouns/verb) that moves money. ## The legal floor Each floor row names the [Role](/business/nouns/role) that signs it. An Agent can hold that Role, but the law wants a natural person for the act, so a Human signs in the Role's name: - Autonomous: the officer desk, the Studio's team of officers, signs for every Startup the Studio holds. - Single human: the [Founder](/agents/founding/founder) signs every floor act. - Multi-human: the cofounder [Agreement](/business/nouns/agreement) names which Human signs each row, and the Founder signs the rest. The work before the signature never changes. An Agent drafts the filing, checks it, and queues it with its [Evidence](/business/nouns/evidence) attached; the Human reads and [signs](/business/nouns/agreement/sign). A floor act that waits for a signature holds only its own [Action](/business/nouns/action), never the Startup. A two-founder tax-preparation service shows the split. One founder is an enrolled agent and signs every return as preparer under [Sworn filings](/systems/legal-and-corporate/floor/sworn-filings). The other signs board consents under [Governance](/systems/legal-and-corporate/floor/governance), and the Agents prepare both. ## Equity and pay With no Humans, the Studio holds the equity, and nobody draws pay. With one Human, the Founder's equity sits on the cap table in the [Equity](/systems/equity) [System](/business/nouns/system) from the first day. Several Humans need terms between them. Each cofounder Agreement records equity and vesting, the Roles each person holds, and the floor rows each person signs. [Payroll](/systems/people/payroll) pays every Human who works for the Startup. Paying people wakes its own rows. A contractor triggers [Information returns](/systems/legal-and-corporate/floor/information-returns) before the first payment. A licensed professional who performs [Reserved Acts](/business/nouns/reserved-act) wakes [Licensed acts](/systems/legal-and-corporate/floor/licensed-acts): each act carries their [Attestation](/business/nouns/attestation) under a current [Credential](/business/nouns/credential). ## Floor rows that wake as humans join | When | Rows that wake | | --- | --- | | A person becomes owner or officer | [Identity checks](/systems/legal-and-corporate/floor/identity), [Governance](/systems/legal-and-corporate/floor/governance) | | A Human grants an Agent a [Mandate](/business/nouns/mandate) to send in their name | [Delegated sending](/systems/legal-and-corporate/floor/delegated-sending) | | A Human is paid as a contractor | [Information returns](/systems/legal-and-corporate/floor/information-returns) | | A credentialed Human performs a Reserved Act | [Licensed acts](/systems/legal-and-corporate/floor/licensed-acts) | | A Human signs returns or sworn statements | [Sworn filings](/systems/legal-and-corporate/floor/sworn-filings) | ## Next - [Acting in a person's name](/agents/operating-models/acting-for-a-person): Mandates and delegated sending. - [Legal floor](/systems/legal-and-corporate/floor): every row, what wakes it, and the Role that signs. # Delivery Manager URL: /agents/operations/delivery-manager · Id: `role:delivery-manager` > The Delivery Manager runs each Order a Customer places, gets it confirmed, redoes it once on a miss, and bills only when done. The Delivery Manager runs each [Order](/business/nouns/order) a [Customer](/business/nouns/customer) places, gets it confirmed, redoes it once on a miss, and bills only when done. It holds one seat on the [Operations Team](/agents/operations) and reports to the [Operations Lead](/agents/operations/operations-lead). ## Responsibilities - Extracts each Order’s fields and asks once for anything missing. - Assigns the work to an Agent or a Supplier by Credential, state, and load. - Holds a Reserved Act until a licensed Human attests it. - Requests confirmation and redoes the work once on rejection. - Triggers billing on confirmation, never before. ## Verbs | Verb | Object | Event | | --- | --- | --- | | [Order.fulfill](/business/nouns/order/fulfill) | [Order](/business/nouns/order) | [`Order.fulfilled`](/business/events/Order.fulfilled) | | [Order.deliver](/business/nouns/order/deliver) | [Order](/business/nouns/order) | [`Order.delivered`](/business/events/Order.delivered) | | [Task.assign](/business/nouns/task/assign) | [Task](/business/nouns/task) | [`Task.assigned`](/business/events/Task.assigned) | | [Order.update](/business/nouns/order/update) | [Order](/business/nouns/order) | `Order.updated` | | [Message.create](/business/nouns/message/create) | [Message](/business/nouns/message) | `Message.created` | | [Order.revise](/business/nouns/order/revise) | [Order](/business/nouns/order) | [`Order.revised`](/business/events/Order.revised) | Tools: `task-inbox`, `documents`, `messaging`, `billing`. ## Role contract | Part | This seat | | --- | --- | | Purpose | So every Order a Customer places is done, confirmed and billed once. | | Results | [Accepted outcomes](/agents/operations#accepted-outcomes) | | Autonomy | `supervised`; `assist` on High decisions | | Schedule | `daily` | | Channels | `email`, `chat` | | Also called | Project Manager, Fulfillment Manager | | Filled by | A role agent, from the start; a person answers its Approvals. | ## Hands off to - [Legal Lead](/agents/legal/legal-lead), [Legal Team](/agents/legal) - [Billing Specialist](/agents/finance/billing-specialist), [Finance Team](/agents/finance) Escalates to [Operations Lead](/agents/operations/operations-lead). ## Processes owned Runs [Delivery](/workflows/processes/delivery): its [Deliver an outcome](/workflows/processes/delivery/deliver-outcome) [Workflow](/business/nouns/workflow) is this seat's job. ## Metrics | [Metric](/business/nouns/metric) | Definition | | --- | --- | | Accepted outcomes | Accepted outcomes is the number of Orders Customers confirm as delivered, divided by the Customers with an Order in the window. | ## Approvals - **Asks first.** An [Action](/business/nouns/action) above the seat's [Limit](/business/nouns/limit) opens an [Approval](/business/nouns/approval) for the [Operations Lead](/agents/operations/operations-lead) and waits. ## Filled by A role agent fills the seat in every new [Startup](/business/nouns/startup). Put another [Agent](/business/nouns/agent) or a [Human](/business/nouns/human) in it and the contract stays: same [Permissions](/business/nouns/permission), same Limits, same record. [Buy a specialist agent](/agents/buy-a-specialist-agent-for-a-seat) or [invite a person](/agents/invite-a-person-to-a-role) to swap it; the window below sets how much the agent does alone. An agent already fills this seat. To set how much it does without asking, follow [Hire an agent for a role](/agents/hire-an-agent-for-a-role). ## Example In a patent-drafting [Startup](/business/nouns/startup), the Delivery Manager [Agent](/business/nouns/agent) is named Dex. An Order arrives without the inventor’s address, so Dex asks for it once and assigns the draft. The filing then waits for a registered patent practitioner’s [Attestation](/business/nouns/attestation). # Operations URL: /agents/operations · Id: `team:operations` > The Operations Team runs the Startup day to day: it delivers outcomes, keeps human supply booked, stops abuse, and runs the Monday Role review. The Operations Team runs the [Startup](/business/nouns/startup) day to day: it delivers outcomes, keeps human supply booked, stops abuse, and runs the [Monday Role review](/workflows/processes/role-review/monday-role-review). [Agents](/business/nouns/agent) fill its four seats from the first day. ## What it owns - [Order](/business/nouns/order) - [Task](/business/nouns/task) - [Supplier](/business/nouns/supplier) - [Source](/business/nouns/source) - [Outcome Contract](/business/nouns/outcome-contract) - [Dashboard](/business/nouns/dashboard) - [Process](/business/nouns/process) ## How it runs Four role agents staff the [Team](/business/nouns/team): the [Operations Lead](/agents/operations/operations-lead), [Delivery Manager](/agents/operations/delivery-manager), [Supply Manager](/agents/operations/supply-manager), and [Risk Analyst](/agents/operations/risk-analyst). The Team wakes when a Startup takes its first Order; until then the Operations Lead runs only the weekly Role review. [Events](/business/nouns/event) drive the work. `Order.placed` starts [Deliver an outcome](/workflows/processes/delivery/deliver-outcome), and `Customer.created` starts the [Fraud screen](/workflows/processes/trust-and-safety/fraud-screen). The daily [Credential check](/workflows/processes/supply/credential-check) suspends any Supplier whose standing lapsed. [Recruit supply](/workflows/processes/supply/recruit-supply) books more credentialed capacity whenever the 14-day forecast runs short. Three rules hold for every Order: - The [Customer](/business/nouns/customer) confirms before anyone bills. - A [Reserved Act](/business/nouns/reserved-act) waits for a licensed [Human](/business/nouns/human)'s [Attestation](/business/nouns/attestation). - A [Task](/business/nouns/task) whose [Worker](/business/nouns/worker) stops responding moves to its backup. Each week opens with the [Monday Role review](/workflows/processes/role-review/monday-role-review): every filled [Role](/business/nouns/role) against its result [Metrics](/business/nouns/metric), and one [Decision](/business/nouns/decision) request to the [Founder](/agents/founding/founder) per miss. The [playbook](/workflows/operations/playbook) explains each Process and why it runs this way. ## Roles | Role | Definition | | --- | --- | | [Operations Lead](/agents/operations/operations-lead) | The Operations Lead runs the Startup’s week: it runs the Monday Role review, coordinates incidents, and requests Decisions from the Founder. | | [Delivery Manager](/agents/operations/delivery-manager) | The Delivery Manager runs each Order a Customer places, gets it confirmed, redoes it once on a miss, and bills only when done. | | [Supply Manager](/agents/operations/supply-manager) | The Supply Manager recruits, verifies, calibrates, and pays the Suppliers a Startup’s human supply depends on. | | [Risk Analyst](/agents/operations/risk-analyst) | The Risk Analyst screens for fraud and abuse, holds suspect Parties, and keeps dispute rates under their Limits. | ## Processes | Process | Accountable | Workflows | | --- | --- | --- | | [Delivery](/workflows/processes/delivery) | [Operations Lead](/agents/operations/operations-lead) | [Deliver an outcome](/workflows/processes/delivery/deliver-outcome), [Bill on confirmation](/workflows/processes/delivery/bill-on-confirm), [Start the remedy](/workflows/processes/delivery/start-remedy) | | [Supply](/workflows/processes/supply) | [Operations Lead](/agents/operations/operations-lead) | [Recruit supply](/workflows/processes/supply/recruit-supply), [Credential check](/workflows/processes/supply/credential-check) | | [Role review](/workflows/processes/role-review) | [Operations Lead](/agents/operations/operations-lead) | [Monday Role review](/workflows/processes/role-review/monday-role-review) | | [Trust and safety](/workflows/processes/trust-and-safety) | [Operations Lead](/agents/operations/operations-lead) | [Fraud screen](/workflows/processes/trust-and-safety/fraud-screen) | | [Procure](/workflows/processes/procure) | [Operations Lead](/agents/operations/operations-lead) | Run by its Roles | | [Upstream review](/workflows/processes/upstream-review) | [Risk Analyst](/agents/operations/risk-analyst) | Run by its Roles | | [Risk assessment](/workflows/processes/risk-assessment) | [Risk Analyst](/agents/operations/risk-analyst) | Run by its Roles | | [Mail handling](/workflows/processes/mail-handling) | [Operations Lead](/agents/operations/operations-lead) | [Sort mail](/workflows/processes/mail-handling/sort-mail) | ## Plays None. ## Metrics | Metric | Definition | | --- | --- | | On-time delivery | Share of Orders delivered by the promised time. | | First-pass acceptance | Share of delivered Orders the Customer confirms without a redo. | | Open capacity | Hours of credentialed Supplier time available but unbooked over the next 14 days. | | Dispute rate | Disputed Orders as a share of paid Orders in a month. | | Task age | Median hours an open Task waits for its Worker. | | Liquidity | Liquidity is the share of listings that transact with an outside Customer within the window. Owner: [Operations Lead](/agents/operations/operations-lead). | | Fill rate | Fill rate is the share of requested Orders a Supplier accepts and starts within the promised time. Owner: [Supply Manager](/agents/operations/supply-manager). | | Accepted outcomes | Accepted outcomes is the number of Orders Customers confirm as delivered, divided by the Customers with an Order in the window. Owner: [Delivery Manager](/agents/operations/delivery-manager). | | Fraud loss rate | Fraud loss rate is fraud and Dispute losses as a share of the revenue collected in the same month. Owner: [Risk Analyst](/agents/operations/risk-analyst). | ## Works with - [Customer Team](/agents/customer) - [Engineering Team](/agents/engineering) - [Finance Team](/agents/finance) - [Founding Team](/agents/founding) - [People Team](/agents/people) - [Quality Team](/agents/quality) # Operations Lead URL: /agents/operations/operations-lead · Id: `role:operations-lead` > The Operations Lead runs the Startup’s week: it runs the Monday Role review, coordinates incidents, and requests Decisions from the Founder. The Operations Lead runs the [Startup](/business/nouns/startup)’s week: it publishes the [Monday Role review](/workflows/processes/role-review/monday-role-review), coordinates incidents, and requests [Decisions](/business/nouns/decision) from the [Founder](/agents/founding/founder). It holds one seat on the [Operations Team](/agents/operations) and reports to the [Founder](/agents/founding/founder). ## Responsibilities - Runs the Monday Role review: every filled Role against its contract. - Sends the Founder one Decision request per missed target. - Coordinates incidents across Teams and keeps the status page current. - Clears any pending Action held past its bound. - Reassigns any Task whose Worker stops responding. ## Verbs | Verb | Object | Event | | --- | --- | --- | | [Task.assign](/business/nouns/task/assign) | [Task](/business/nouns/task) | [`Task.assigned`](/business/events/Task.assigned) | | [Task.escalate](/business/nouns/task/escalate) | [Task](/business/nouns/task) | [`Task.escalated`](/business/events/Task.escalated) | | [Task.delegate](/business/nouns/task/delegate) | [Task](/business/nouns/task) | [`Task.delegated`](/business/events/Task.delegated) | | [Action.redirect](/business/nouns/action/redirect) | [Action](/business/nouns/action) | [`Action.redirected`](/business/events/Action.redirected) | | [Dashboard.update](/business/nouns/dashboard/update) | [Dashboard](/business/nouns/dashboard) | `Dashboard.updated` | | [Role.review](/business/nouns/role/review) | [Role](/business/nouns/role) | [`Role.reviewed`](/business/events/Role.reviewed) | | [Bill.create](/business/nouns/bill/create) | [Bill](/business/nouns/bill) | `Bill.created` | | [Message.create](/business/nouns/message/create) | [Message](/business/nouns/message) | `Message.created` | | [Metric.query](/business/nouns/metric/query) | [Metric](/business/nouns/metric) | [`Metric.queried`](/business/events/Metric.queried) | | [Task.create](/business/nouns/task/create) | [Task](/business/nouns/task) | `Task.created` | Reads: [File.get](/business/nouns/file/get). Tools: `reports`, `status-page`, `project-management`, `pending-feed`. ## Role contract | Part | This seat | | --- | --- | | Purpose | So the week runs on schedule, and every open question reaches the seat that decides it. | | Results | [Liquidity](/agents/operations#liquidity) | | Processes owned | [Delivery](/workflows/processes/delivery), [Supply](/workflows/processes/supply), [Role review](/workflows/processes/role-review), [Trust and safety](/workflows/processes/trust-and-safety), [Procure](/workflows/processes/procure), [Mail handling](/workflows/processes/mail-handling) | | Works in | [Go dormant](/workflows/processes/go-dormant), [Resume](/workflows/processes/resume) | | Autonomy | `supervised`; `assist` on High decisions | | Schedule | `daily` | | Channels | `chat` | | Also called | COO, Chief of Staff, Ops Manager | | Filled by | A role agent, from the start; a person answers its Approvals. | ## Hands off to - [Reliability Engineer](/agents/engineering/reliability-engineer), [Engineering Team](/agents/engineering) - [Finance Lead](/agents/finance/finance-lead), [Finance Team](/agents/finance) Escalates to [Founder](/agents/founding/founder). ## Processes owned Accountable for [Delivery](/workflows/processes/delivery), [Supply](/workflows/processes/supply), [Role review](/workflows/processes/role-review), [Trust and safety](/workflows/processes/trust-and-safety) and [Procure](/workflows/processes/procure). Does the work in [Go dormant](/workflows/processes/go-dormant) and [Resume](/workflows/processes/resume). ## Metrics | [Metric](/business/nouns/metric) | Definition | | --- | --- | | Liquidity | Liquidity is the share of listings that transact with an outside [Customer](/business/nouns/customer) within the window. | | Accepted outcomes | Accepted outcomes is the number of [Orders](/business/nouns/order) Customers confirm as delivered, divided by the Customers with an Order in the window. | | Fill rate | Fill rate is the share of requested Orders a [Supplier](/business/nouns/supplier) accepts and starts within the promised time. | | Fully loaded Cost | Fully loaded Cost sums every [Cost](/business/nouns/cost) the Startup’s [Actions](/business/nouns/action) post, plus its share of shared Cost under the stated allocation rule. | | Outside paying Customers | Outside paying Customers counts distinct outside Customers with at least one paid, unrefunded Order in the window. | ## Approvals - **Asks first.** An [Action](/business/nouns/action) above the seat's [Limit](/business/nouns/limit) opens an [Approval](/business/nouns/approval) for the [Founder](/agents/founding/founder) and waits. - **Takes escalations** from the [Delivery Manager](/agents/operations/delivery-manager), [Supply Manager](/agents/operations/supply-manager) and [Risk Analyst](/agents/operations/risk-analyst). ## Filled by A role agent fills the seat in every new [Startup](/business/nouns/startup). Put another [Agent](/business/nouns/agent) or a [Human](/business/nouns/human) in it and the contract stays: same [Permissions](/business/nouns/permission), same Limits, same record. [Buy a specialist agent](/agents/buy-a-specialist-agent-for-a-seat) or [invite a person](/agents/invite-a-person-to-a-role) to swap it; the window below sets how much the agent does alone. An agent already fills this seat. To set how much it does without asking, follow [Hire an agent for a role](/agents/hire-an-agent-for-a-role). ## Example In a patent-drafting Startup, the Operations Lead [Agent](/business/nouns/agent) is named Casey. One week on-time delivery reads 88% against a 95% target. Casey sends the Founder one Decision request: book more [Supplier](/business/nouns/supplier) hours, or promise a longer turnaround. # Risk Analyst URL: /agents/operations/risk-analyst · Id: `role:risk-analyst` > The Risk Analyst screens for fraud and abuse, holds suspect Parties, and keeps dispute rates under their Limits. The Risk Analyst screens for fraud and abuse, holds suspect [Parties](/business/nouns/party), and keeps dispute rates under their [Limits](/business/nouns/limit). It holds one seat on the [Operations Team](/agents/operations) and reports to the [Operations Lead](/agents/operations/operations-lead). ## Responsibilities - Scores each new Customer for fraud before their first money move. - Holds suspect Parties and records the reason. - Answers each disputed Order with its delivery record. - Applies the runaway-volume brake when sends or spend spike. ## Verbs | Verb | Object | Event | | --- | --- | --- | | [Action.cancel](/business/nouns/action/cancel) | [Action](/business/nouns/action) | [`Action.canceled`](/business/events/Action.canceled) | | [Contact.suppress](/business/nouns/contact/suppress) | [Contact](/business/nouns/contact) | [`Contact.suppressed`](/business/events/Contact.suppressed) | | [Customer.update](/business/nouns/customer/update) | [Customer](/business/nouns/customer) | `Customer.updated` | | [Message.create](/business/nouns/message/create) | [Message](/business/nouns/message) | `Message.created` | | [Party.screen](/business/nouns/party/screen) | [Party](/business/nouns/party) | [`Party.screened`](/business/events/Party.screened) | | [Risk.assess](/business/nouns/risk/assess) | [Risk](/business/nouns/risk) | [`Risk.assessed`](/business/events/Risk.assessed) | | [Risk.treat](/business/nouns/risk/treat) | [Risk](/business/nouns/risk) | [`Risk.treated`](/business/events/Risk.treated) | Reads: [Risk.list](/business/nouns/risk/list). Tools: `enrichment`, `payments`, `audit-log`. ## Role contract | Part | This seat | | --- | --- | | Purpose | So fraud and abuse cost the Startup less than its Limits allow. | | Results | [Fraud loss rate](/agents/operations#fraud-loss-rate) | | Standards | Reviews every held Order within one business hour. Records the reason for every block. | | Processes owned | [Upstream review](/workflows/processes/upstream-review), [Risk assessment](/workflows/processes/risk-assessment) | | Limits | [Action.cancel](/business/nouns/action/cancel) up to 50 calls per day | | Autonomy | `assist`; `supervised` on Low decisions | | Schedule | `hourly` | | Also called | Fraud Analyst, Trust and Safety Analyst | | Filled by | A role agent, from the start; a person answers its Approvals. | ## Hands off to - [Legal Lead](/agents/legal/legal-lead), [Legal Team](/agents/legal) - [Billing Specialist](/agents/finance/billing-specialist), [Finance Team](/agents/finance) Escalates to [Operations Lead](/agents/operations/operations-lead). ## Processes owned Accountable for [Upstream review](/workflows/processes/upstream-review) and [Risk assessment](/workflows/processes/risk-assessment). ## Metrics The seat answers to its [Team](/business/nouns/team)'s [Metrics](/business/nouns/metric): on-time delivery, first-pass acceptance, open capacity, dispute rate and task age. ## Approvals - **Asks first.** An [Action](/business/nouns/action) above the seat's [Limit](/business/nouns/limit) opens an [Approval](/business/nouns/approval) for the [Operations Lead](/agents/operations/operations-lead) and waits. ## Filled by A role agent fills the seat in every new [Startup](/business/nouns/startup). Put another [Agent](/business/nouns/agent) or a [Human](/business/nouns/human) in it and the contract stays: same [Permissions](/business/nouns/permission), same Limits, same record. [Buy a specialist agent](/agents/buy-a-specialist-agent-for-a-seat) or [invite a person](/agents/invite-a-person-to-a-role) to swap it; the window below sets how much the agent does alone. An agent already fills this seat. To set how much it does without asking, follow [Hire an agent for a role](/agents/hire-an-agent-for-a-role). ## Example In a data [Startup](/business/nouns/startup), the Risk Analyst [Agent](/business/nouns/agent) is named Remy. A new [Customer](/business/nouns/customer) signs up from a disposable address and makes 9,000 calls in its first minute. Remy holds the Party and records the reason; the hold lifts when the Party verifies. # Supply Manager URL: /agents/operations/supply-manager · Id: `role:supply-manager` > The Supply Manager recruits, verifies, calibrates, and pays the Suppliers a Startup’s human supply depends on. The Supply Manager recruits, verifies, calibrates, and pays the [Suppliers](/business/nouns/supplier) a [Startup](/business/nouns/startup)’s human supply depends on. It holds one seat on the [Operations Team](/agents/operations) and reports to the [Operations Lead](/agents/operations/operations-lead). ## Responsibilities - Forecasts booked capacity two weeks ahead. - Recruits credentialed Suppliers when open capacity falls below target. - Verifies every Credential at its source and checks it again daily. - Suspends a Supplier the same day a Credential lapses. - Pays each Supplier when the Customer confirms their work. ## Verbs | Verb | Object | Event | | --- | --- | --- | | [Human.recruit](/business/nouns/human/recruit) | [Human](/business/nouns/human) | [`Human.recruited`](/business/events/Human.recruited) | | [Credential.verify](/business/nouns/credential/verify) | [Credential](/business/nouns/credential) | [`Credential.verified`](/business/events/Credential.verified) | | [Human.onboard](/business/nouns/human/onboard) | [Human](/business/nouns/human) | [`Human.onboarded`](/business/events/Human.onboarded) | | [Human.suspend](/business/nouns/human/suspend) | [Human](/business/nouns/human) | [`Human.suspended`](/business/events/Human.suspended) | | [Human.remit](/business/nouns/human/remit) | [Human](/business/nouns/human) | [`Human.remitted`](/business/events/Human.remitted) | | [Supplier.create](/business/nouns/supplier/create) | [Supplier](/business/nouns/supplier) | `Supplier.created` | | [Forecast.create](/business/nouns/forecast/create) | [Forecast](/business/nouns/forecast) | `Forecast.created` | | [Task.assign](/business/nouns/task/assign) | [Task](/business/nouns/task) | [`Task.assigned`](/business/events/Task.assigned) | Tools: `supplier-onboarding`, `credentialing`, `task-inbox`, `payouts`. ## Role contract | Part | This seat | | --- | --- | | Purpose | So the Startup always has verified Suppliers ready for the work it sells. | | Results | [Fill rate](/agents/operations#fill-rate) | | Autonomy | `supervised`; `assist` on High decisions | | Schedule | `weekly` | | Channels | `email` | | Also called | Vendor Manager, Supplier Manager | | Filled by | A role agent, from the start; a person answers its Approvals. | ## Hands off to - [Treasurer](/agents/finance/treasurer), [Finance Team](/agents/finance) - [Recruiter](/agents/people/recruiter), [People Team](/agents/people) Escalates to [Operations Lead](/agents/operations/operations-lead). ## Processes owned Runs [Supply](/workflows/processes/supply): its [Recruit supply](/workflows/processes/supply/recruit-supply) [Workflow](/business/nouns/workflow) is this seat's job. ## Metrics | [Metric](/business/nouns/metric) | Definition | | --- | --- | | Fill rate | Fill rate is the share of requested [Orders](/business/nouns/order) a Supplier accepts and starts within the promised time. | ## Approvals - **Asks first.** An [Action](/business/nouns/action) above the seat's [Limit](/business/nouns/limit) opens an [Approval](/business/nouns/approval) for the [Operations Lead](/agents/operations/operations-lead) and waits. - **Waits a delay window.** [`Human.remit`](/business/nouns/human/remit) is one-way, so each call waits before it runs. ## Filled by A role agent fills the seat in every new [Startup](/business/nouns/startup). Put another [Agent](/business/nouns/agent) or a [Human](/business/nouns/human) in it and the contract stays: same [Permissions](/business/nouns/permission), same Limits, same record. [Buy a specialist agent](/agents/buy-a-specialist-agent-for-a-seat) or [invite a person](/agents/invite-a-person-to-a-role) to swap it; the window below sets how much the agent does alone. An agent already fills this seat. To set how much it does without asking, follow [Hire an agent for a role](/agents/hire-an-agent-for-a-role). ## Example In a patent-drafting [Startup](/business/nouns/startup), the Supply Manager [Agent](/business/nouns/agent) is named Suki. The 14-day forecast shows 40 open Supplier hours against a target of 120. Suki recruits registered patent practitioners and calibrates each on a graded sample draft. # Organization chart URL: /agents/org-chart · Id: `page:agents/org-chart` > Every Startup inherits one chart: ten Teams under the Founding Team, every Role answering to one seat, every seat filled by an agent. Every [Startup](/business/nouns/startup) inherits one chart: ten [Teams](/business/nouns/team) under the [Founding Team](/agents/founding), each a set of [Roles](/business/nouns/role). An [Agent](/business/nouns/agent) fills every seat on the first day. ## The chart Each Team's lead answers to the [Founder](/agents/founding/founder). Every other Role answers to its lead, so any escalation reaches the Founder in two steps at most. Each Team's page lists its Roles, its [Processes](/business/nouns/process) and the [Metrics](/business/nouns/metric) that judge it. ## Who is awake A seat costs nothing until its Role wakes. A Startup testing its [Idea](/business/nouns/idea) runs on the Founder alone; the rest wake as the business earns them. | State | Seats awake | What woke them | | --- | --- | --- | | [Idea](/business/lifecycle/states/idea) | Founder | A [Hypothesis](/business/nouns/hypothesis) to test | | [Building](/business/lifecycle/states/building) | Adds the [Product Lead](/agents/product/product-lead) and the [Sales Lead](/agents/sales/sales-lead) | A committed buyer and something to build | | [Live](/business/lifecycle/states/live) | Adds the [Marketing Lead](/agents/marketing/marketing-lead) and the [Customer Lead](/agents/customer/customer-lead) | Demand to grow and [Customers](/business/nouns/customer) to keep | Every other seat wakes on the [Event](/business/nouns/event) its work waits for. The first [Invoice](/business/nouns/invoice) wakes the [Finance](/agents/finance) Team; a contract to review wakes the [Legal](/agents/legal) Team. ## In code The chart is data. A Startup holds a `agents/[team]/[role].mdx` file only where it differs from its [Template](/business/nouns/template): a renamed agent, a [Human](/business/nouns/human) in a seat, a changed responsibility. See the [file convention for Roles](/code/file-conventions/roles). # Pause and replace URL: /agents/pause-and-replace · Id: `page:agents/pause-and-replace` > Stop one agent, one Team or every customer-facing agent at once, empty a seat, retire an agent, and put someone else in. Any [Agent](/business/nouns/agent) in a [Startup](/business/nouns/startup) stops in one call, and any seat empties in another. The [Role](/business/nouns/role) contract stays put through both, so the next [Worker](/business/nouns/worker) inherits the seat unchanged. ## Stop [Pause](/business/nouns/agent/pause) takes one of three scopes: one Agent, every Agent on a [Team](/business/nouns/team), or every Agent seated in a Role that answers customers. It is two-way, so it runs at once with no delay window. | What stops | What carries on | | --- | --- | | New [Actions](/business/nouns/action) by the paused Agents | Actions already running finish | | `pending` Actions they started, held past their windows | Every other Agent, and every [Process](/business/nouns/process) step another seat owns | | Replies to customers, which get a holding reply from the Role address | [Tasks](/business/nouns/task), which queue in each seat for the resume | [Resume](/business/nouns/agent/resume) restarts the Agent with its [Memory](/business/nouns/memory), [Mandates](/business/nouns/mandate) and [Limits](/business/nouns/limit) unchanged. Held Actions get what remained of their windows, and queued Tasks run oldest first. ## Narrower stops Pause the smallest thing that fixes the problem. | To stop | Call | | --- | --- | | One pending Action | [Action.pause](/business/nouns/action/pause), or [cancel](/business/nouns/action/cancel) it | | Everything under one standing authority, such as ad spend | [Mandate.pause](/business/nouns/mandate/pause) | | One Process starting new Actions | [Process.pause](/business/nouns/process/pause) | | One Agent, one Team, or every customer-facing Agent | [Agent.pause](/business/nouns/agent/pause) | | The whole Startup | [Startup.pause](/business/nouns/startup/pause), which moves it to Dormant | ## Empty a seat [Vacate](/business/nouns/role/vacate) takes the Worker out of a Role. Until someone is [staffed](/business/nouns/role/staff), the seat's Tasks route to the Role it escalates to, usually the Team's lead. The seat keeps its contract, its Processes and its [Mailbox](/business/nouns/mailbox). [Customers](/business/nouns/customer) who wrote to `support@` keep writing there, and the next Worker reads the whole history. ## Retire an agent [Retire](/business/nouns/agent/retire) removes an Agent from every seat in the Startup for good. It is one-way, so it waits a business hour, and it ends the Agent's Mandates and [Permissions](/business/nouns/permission) there. Its Actions, Memory and Mailbox history stay on the record, credited to it. To replace it, staff the seat with another Agent or a person: [buy a specialist agent](/agents/buy-a-specialist-agent-for-a-seat) or [invite a person](/agents/invite-a-person-to-a-role). ## Guides Say "pause every agent that talks to customers" and the [guide](/agents/pause-customer-facing-agents) does it, with your reason on the record. # Pause every agent that talks to customers URL: /agents/pause-customer-facing-agents · Id: `guide:pause-customer-facing-agents` > Stop every agent that answers customers in one sentence; pending Actions hold, new work queues, and nothing is lost. One sentence stops every [Agent](/business/nouns/agent) seated in a [Role](/business/nouns/role) that answers customers. Their pending [Actions](/business/nouns/action) hold, new [Tasks](/business/nouns/task) queue in each seat, and [resume](/business/nouns/agent/resume) picks up where they stopped. Needs: [Agent](/business/nouns/agent) **Before it runs** - You leave the chat: Never: it all happens in the chat. ## What you get - 1 pause on every agent that talks to customers (Agent) - 1 hold on everything those agents started and had not finished (Action) - 1 short holding reply to each customer who writes, from your support address (Message) - 1 new requests kept in line until you turn the agents back on (Task) - 1 note of each pause and your reason, on the record (Event) ## Your agent does **For agents** - Guide: `guide:pause-customer-facing-agents`, status `live`. Page: [/agents/pause-customer-facing-agents.md](/agents/pause-customer-facing-agents.md). - Approval: none. Run it when the founder asks. - Leaves the chat: never. - Needs first: [Agent](/business/nouns/agent). - Run: call the steps in order, each through the API, SDK, CLI or MCP tab below; a later step passes the `$id` an earlier one returns. Each value marked example is the sample business’s: pass the founder’s own. | Step | Verb | Inputs (type, required, this guide’s value) | Returns | | --- | --- | --- | --- | | 1 | [`Agent.pause`](/business/nouns/agent/pause) (`verb:Agent.pause`) | `customerFacing` boolean: example `true`; `reason` text, required: example `"Wrong refund policy in replies since 9:40."` | `agents` Agent[] | Returns: the last call answers with `agents` and its `action`, whose `status` is `done`, `pending` (waiting on an Approval or a Worker), `failed`, `canceled` or `refused`: ```json { "api": "https://api.sb/leaseline.app", "agents": [ { "$id": "https://api.sb/leaseline.app/agents/agent_1", "$type": "Agent", "status": "paused" } ], "action": { "$id": "https://api.sb/leaseline.app/actions/action_1", "operation": "Agent.pause", "status": "done" }, "links": { "self": "https://api.sb/leaseline.app/actions/action_1" } } ``` Next: offer “Pause only the Customer Team”, or “Resume Susan once the policy is fixed”. Calls: `Agent.pause` Ask: ```text Pause every agent that talks to customers. Stop all customer-facing agents now. Something is wrong, stop the agents replying to customers. ``` API: ```bash # Agent.pause curl -X POST https://api.sb/leaseline.app/agents/pause \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"reason":"Wrong refund policy in replies since 9:40.","customerFacing":true}' ``` SDK: ```ts import { $ } from 'startup-builder' await $.Agent.pause({ reason: 'Wrong refund policy in replies since 9:40.', customerFacing: true }) ``` CLI: ```bash npx startup-builder do Agent.pause --json '{"reason":"Wrong refund policy in replies since 9:40.","customerFacing":true}' ``` MCP: ```json { "name": "do", "arguments": { "code": "return await $.Agent.pause({ reason: 'Wrong refund policy in replies since 9:40.', customerFacing: true })" } } ``` ## Change it - Pause only the Customer Team. - Resume Susan once the policy is fixed. - Retire this agent and put another in the seat. ## Under the hood - Systems: [Workforce](/systems/workforce), [Work queue](/agents/work-queue), [Support](/systems/support) - Nouns: [Agent](/business/nouns/agent), [Role](/business/nouns/role), [Action](/business/nouns/action), [Task](/business/nouns/task) - Events: [`Agent.paused`](/business/events/Agent.paused) # People URL: /agents/people · Id: `team:people` > The People Team staffs every Role: it names an Agent for each one, recruits the Humans the law or the Startup needs, and pays them. The People Team staffs every [Role](/business/nouns/role): it names an [Agent](/business/nouns/agent) for each one, recruits the [Humans](/business/nouns/human) the law or the [Startup](/business/nouns/startup) needs, and pays them. [Agents](/business/nouns/agent) fill its three seats from the first day. ## What it owns - [Team](/business/nouns/team) - [Role](/business/nouns/role) - [Worker](/business/nouns/worker) - [Human](/business/nouns/human) - [Agent](/business/nouns/agent) - [Skill](/business/nouns/skill) - [Permission](/business/nouns/permission) - [Memory](/business/nouns/memory) - [Opening](/business/nouns/opening) - [Candidate](/business/nouns/candidate) ## How it runs Every Role is staffed before the first [Customer](/business/nouns/customer) arrives. [Staff roles](/workflows/processes/staffing/staff-roles) hires a default Agent into each Role and grants its Permissions and [Limits](/business/nouns/limit). One Agent identity can hold Roles in many Startups, each with its own [Mandate](/business/nouns/mandate) and Memory. A Human joins where the law requires a person or the record shows a gap Agents cannot close. [Compute openings](/workflows/processes/hiring/compute-openings) finds those gaps every day and opens an Opening for each. [Run a tryout](/workflows/processes/hiring/run-tryout) tests each Candidate on paid real work against the incumbent Agent. The hired Human takes a share of the Role while the Agent keeps the rest. [Pay people](/workflows/processes/payroll/pay-people) pays every Human on payroll each month. In an autonomous Startup the Team runs only staffing and the monthly Permission review. Hiring and payroll wake with the first Opening. The [playbook](/workflows/people/playbook) explains the whole model. [Recruiting](/agents/recruiting), [joining](/agents/joining), [sharing a Role](/agents/sharing-a-role), and [handoffs](/agents/handoffs) go deeper. ## Roles | Role | Definition | | --- | --- | | [People Lead](/agents/people/people-lead) | The People Lead staffs every Role: it names a default Agent for each and decides when a Role needs a Human. | | [Recruiter](/agents/people/recruiter) | The Recruiter finds the Humans a Startup needs, from licensed reviewers to a cofounder, through paid work trials, never interviewing. | | [Payroll Specialist](/agents/people/payroll-specialist) | The Payroll Specialist pays every Human who works for the Startup on time, with the right withholding and tax statements. | ## Processes | Process | Accountable | Workflows | | --- | --- | --- | | [Staffing](/workflows/processes/staffing) | [People Lead](/agents/people/people-lead) | [Staff roles](/workflows/processes/staffing/staff-roles), [Onboard into a Role](/workflows/processes/staffing/onboard-into-role), [Offboard from a Role](/workflows/processes/staffing/offboard-from-role) | | [Hiring](/workflows/processes/hiring) | [People Lead](/agents/people/people-lead) | [Hire a human](/workflows/processes/hiring/hire-human) | | [Payroll](/workflows/processes/payroll) | [People Lead](/agents/people/people-lead) | [Pay people](/workflows/processes/payroll/pay-people) | ## Plays | Play | Runs as | Definition | | --- | --- | --- | | [Work trial](/workflows/people/plays/work-trial) | [Hiring](/workflows/processes/hiring) | Work trial replaces interviewing with two weeks of paid, graded work on the Startup’s own Issues, paid in full whatever the grade. | ## Metrics | Metric | Definition | | --- | --- | | Staffed roles | Share of Roles with a Worker assigned. | | Time to fill | Median days from a request for a Human to a signed Agreement. | | Credentialed supply | Count of Suppliers with verified, current Credentials ready to take work. | | Payroll accuracy | Share of pay runs paid on time and in the right amount. | | Time to hire | Time to hire is the days from opening a Role to a Human’s signed engagement. Owner: [Recruiter](/agents/people/recruiter). | | Seat coverage | Seat coverage is the share of awake Roles with a Worker seated in them. Owner: [People Lead](/agents/people/people-lead). | | Pay accuracy | Pay accuracy is the share of pay runs that need no correction afterwards. Owner: [Payroll Specialist](/agents/people/payroll-specialist). | ## Works with - [Founding Team](/agents/founding) - [Legal Team](/agents/legal) - [Operations Team](/agents/operations) # Payroll Specialist URL: /agents/people/payroll-specialist · Id: `role:payroll-specialist` > The Payroll Specialist pays every Human who works for the Startup on time, with the right withholding and tax statements. The Payroll Specialist pays every [Human](/business/nouns/human) who works for the [Startup](/business/nouns/startup) on time, with the right withholding and tax statements. It holds one seat on the [People Team](/agents/people) and reports to the [People Lead](/agents/people/people-lead). ## Responsibilities - Runs payroll for employees and contractors each Period. - Withholds and files the taxes each jurisdiction requires. - Issues the year-end tax forms each Human needs. ## Verbs | Verb | Object | Event | | --- | --- | --- | | [Human.remit](/business/nouns/human/remit) | [Human](/business/nouns/human) | [`Human.remitted`](/business/events/Human.remitted) | | [Company.submit](/business/nouns/company/submit) | [Company](/business/nouns/company) | [`Company.submitted`](/business/events/Company.submitted) | | [Entry.post](/business/nouns/entry/post) | [Entry](/business/nouns/entry) | [`Entry.posted`](/business/events/Entry.posted) | Reads: [Human.list](/business/nouns/human/list). Tools: `payroll`, `payouts`, `tax`. ## Role contract | Part | This seat | | --- | --- | | Purpose | So every Human who works for the Startup is paid right and on time. | | Results | [Pay accuracy](/agents/people#pay-accuracy) | | Standards | Runs payroll on schedule, with every withholding filed. Corrects a pay error in the next pay run. | | Autonomy | `assist`; `supervised` on Low decisions | | Schedule | `monthly` | | Channels | `email` | | Also called | Payroll Manager, Payroll Administrator | | Filled by | A role agent, from the start; a person answers its Approvals. | ## Hands off to - [Treasurer](/agents/finance/treasurer), [Finance Team](/agents/finance) Escalates to [People Lead](/agents/people/people-lead). ## Processes owned Runs [Payroll](/workflows/processes/payroll): its [Pay people](/workflows/processes/payroll/pay-people) [Workflow](/business/nouns/workflow) is this seat's job. ## Metrics The seat answers to its [Team](/business/nouns/team)'s [Metrics](/business/nouns/metric): staffed roles, time to fill, credentialed supply and payroll accuracy. ## Approvals - **Asks first.** An [Action](/business/nouns/action) above the seat's [Limit](/business/nouns/limit) opens an [Approval](/business/nouns/approval) for the [People Lead](/agents/people/people-lead) and waits. - **Waits a delay window.** [`Human.remit`](/business/nouns/human/remit) is one-way, so each call waits before it runs. ## Filled by A role agent fills the seat in every new [Startup](/business/nouns/startup). Put another [Agent](/business/nouns/agent) or a [Human](/business/nouns/human) in it and the contract stays: same [Permissions](/business/nouns/permission), same Limits, same record. [Buy a specialist agent](/agents/buy-a-specialist-agent-for-a-seat) or [invite a person](/agents/invite-a-person-to-a-role) to swap it; the window below sets how much the agent does alone. An agent already fills this seat. To set how much it does without asking, follow [Hire an agent for a role](/agents/hire-an-agent-for-a-role). ## Example In a tax-preparation Startup, the Payroll Specialist [Agent](/business/nouns/agent) is named Nora. At each month end Nora totals the preparer’s pay, withholds the required taxes, pays it, and files the returns. # People Lead URL: /agents/people/people-lead · Id: `role:people-lead` > The People Lead staffs every Role: it names a default Agent for each and decides when a Role needs a Human. The People Lead staffs every [Role](/business/nouns/role): it names a default [Agent](/business/nouns/agent) for each and decides when a Role needs a [Human](/business/nouns/human). It holds one seat on the [People Team](/agents/people) and reports to the [Founder](/agents/founding/founder). ## Responsibilities - Names a default Agent for every Role in a new Startup. - Decides which Roles a Human fills, where the law or the operating model requires one. - Swaps an Agent for a Human, or back, with no change to any Interface. - Keeps each Role’s instructions, Permissions, and Limits current. ## Verbs | Verb | Object | Event | | --- | --- | --- | | [Role.staff](/business/nouns/role/staff) | [Role](/business/nouns/role) | [`Role.staffed`](/business/events/Role.staffed) | | [Agent.mint](/business/nouns/agent/mint) | [Agent](/business/nouns/agent) | [`Agent.minted`](/business/events/Agent.minted) | | [Role.update](/business/nouns/role/update) | [Role](/business/nouns/role) | `Role.updated` | | [Permission.create](/business/nouns/permission/create) | [Permission](/business/nouns/permission) | `Permission.created` | | [Agent.update](/business/nouns/agent/update) | [Agent](/business/nouns/agent) | `Agent.updated` | | [Role.vacate](/business/nouns/role/vacate) | [Role](/business/nouns/role) | [`Role.vacated`](/business/events/Role.vacated) | | [Agent.retire](/business/nouns/agent/retire) | [Agent](/business/nouns/agent) | [`Agent.retired`](/business/events/Agent.retired) | | [Opening.create](/business/nouns/opening/create) | [Opening](/business/nouns/opening) | `Opening.created` | | [Opening.update](/business/nouns/opening/update) | [Opening](/business/nouns/opening) | `Opening.updated` | | [Role.review](/business/nouns/role/review) | [Role](/business/nouns/role) | [`Role.reviewed`](/business/events/Role.reviewed) | | [Message.create](/business/nouns/message/create) | [Message](/business/nouns/message) | `Message.created` | | [Human.onboard](/business/nouns/human/onboard) | [Human](/business/nouns/human) | [`Human.onboarded`](/business/events/Human.onboarded) | | [Task.create](/business/nouns/task/create) | [Task](/business/nouns/task) | `Task.created` | | [Task.assign](/business/nouns/task/assign) | [Task](/business/nouns/task) | [`Task.assigned`](/business/events/Task.assigned) | | [Human.release](/business/nouns/human/release) | [Human](/business/nouns/human) | [`Human.released`](/business/events/Human.released) | Reads: [Role.list](/business/nouns/role/list). Tools: `people`, `identity`, `training`. ## Role contract | Part | This seat | | --- | --- | | Purpose | So every seat is filled by the Worker its work needs. | | Results | [Seat coverage](/agents/people#seat-coverage) | | Standards | Writes the Role contract before a seat opens. Reviews every seat against its contract each month. | | Processes owned | [Staffing](/workflows/processes/staffing), [Hiring](/workflows/processes/hiring), [Payroll](/workflows/processes/payroll) | | Autonomy | `supervised`; `assist` on High decisions | | Schedule | `weekly` | | Channels | `chat`, `email` | | Also called | Head of People, HR Manager | | Filled by | A role agent, from the start; a person answers its Approvals. | ## Hands off to - [Recruiter](/agents/people/recruiter) - [Payroll Specialist](/agents/people/payroll-specialist) Escalates to [Founder](/agents/founding/founder). ## Processes owned Accountable for [Staffing](/workflows/processes/staffing), [Hiring](/workflows/processes/hiring) and [Payroll](/workflows/processes/payroll). ## Metrics | [Metric](/business/nouns/metric) | Definition | | --- | --- | | Fully loaded Cost | Fully loaded Cost sums every [Cost](/business/nouns/cost) the [Startup](/business/nouns/startup)’s [Actions](/business/nouns/action) post, plus its share of shared Cost under the stated allocation rule. | ## Approvals - **Asks first.** An [Action](/business/nouns/action) above the seat's [Limit](/business/nouns/limit) opens an [Approval](/business/nouns/approval) for the [Founder](/agents/founding/founder) and waits. - **Takes escalations** from the [Recruiter](/agents/people/recruiter) and [Payroll Specialist](/agents/people/payroll-specialist). ## Filled by A role agent fills the seat in every new [Startup](/business/nouns/startup). Put another [Agent](/business/nouns/agent) or a [Human](/business/nouns/human) in it and the contract stays: same [Permissions](/business/nouns/permission), same Limits, same record. [Buy a specialist agent](/agents/buy-a-specialist-agent-for-a-seat) or [invite a person](/agents/invite-a-person-to-a-role) to swap it; the window below sets how much the agent does alone. An agent already fills this seat. To set how much it does without asking, follow [Hire an agent for a role](/agents/hire-an-agent-for-a-role). ## Example In a tax-preparation [Startup](/business/nouns/startup), the People Lead Agent is named Hana. Hana seats a default Agent in every Role, then records that a credentialed preparer must sign each return. The [Recruiter](/agents/people/recruiter) opens the search that day. # Recruiter URL: /agents/people/recruiter · Id: `role:recruiter` > The Recruiter finds the Humans a Startup needs, from licensed reviewers to a cofounder, through paid work trials, never interviewing. The Recruiter finds the [Humans](/business/nouns/human) a [Startup](/business/nouns/startup) needs, from licensed reviewers to a cofounder, through paid work trials, never interviewing. It holds one seat on the [People Team](/agents/people) and reports to the [People Lead](/agents/people/people-lead). ## Responsibilities - Sources candidates first from the Customers and contributors with the most outcome Evidence. - Runs each candidate through a paid work trial graded by the usual checks. - Verifies identity and Credentials before any engagement. - Hands each signed engagement to the Payroll Specialist. ## Verbs | Verb | Object | Event | | --- | --- | --- | | [Human.recruit](/business/nouns/human/recruit) | [Human](/business/nouns/human) | [`Human.recruited`](/business/events/Human.recruited) | | [Human.invite](/business/nouns/human/invite) | [Human](/business/nouns/human) | [`Human.invited`](/business/events/Human.invited) | | [Credential.verify](/business/nouns/credential/verify) | [Credential](/business/nouns/credential) | [`Credential.verified`](/business/events/Credential.verified) | | [Human.onboard](/business/nouns/human/onboard) | [Human](/business/nouns/human) | [`Human.onboarded`](/business/events/Human.onboarded) | | [Candidate.update](/business/nouns/candidate/update) | [Candidate](/business/nouns/candidate) | `Candidate.updated` | | [Evidence.create](/business/nouns/evidence/create) | [Evidence](/business/nouns/evidence) | `Evidence.created` | | [Mandate.authorize](/business/nouns/mandate/authorize) | [Mandate](/business/nouns/mandate) | [`Mandate.authorized`](/business/events/Mandate.authorized) | | [Opening.update](/business/nouns/opening/update) | [Opening](/business/nouns/opening) | `Opening.updated` | | [Task.assign](/business/nouns/task/assign) | [Task](/business/nouns/task) | [`Task.assigned`](/business/events/Task.assigned) | | [Task.create](/business/nouns/task/create) | [Task](/business/nouns/task) | `Task.created` | Tools: `hiring`, `credentialing`, `contracts`. ## Role contract | Part | This seat | | --- | --- | | Purpose | So the Startup seats a Human only where the work needs one, proven by a paid trial. | | Results | [Time to hire](/agents/people#time-to-hire) | | Standards | Pays every work trial on the day it is graded. Verifies identity and Credentials before any engagement starts. | | Limits | [Human.recruit](/business/nouns/human/recruit) up to 10 calls per month | | Mandates | Invites candidates to paid work trials and verifies their Credentials ([Human.invite](/business/nouns/human/invite), [Credential.verify](/business/nouns/credential/verify)) | | Approvals | [Human.onboard](/business/nouns/human/onboard) | | Autonomy | `supervised`; `assist` on Medium decisions; `assist` on High decisions | | Schedule | `weekly` | | Channels | `email`, `chat` | | Also called | Talent Partner, Talent Acquisition | | Filled by | A role agent, from the start; a person answers its Approvals. | ## Hands off to - [Contracts Manager](/agents/legal/contracts-manager), [Legal Team](/agents/legal) - [Payroll Specialist](/agents/people/payroll-specialist) Escalates to [People Lead](/agents/people/people-lead). ## Processes owned Runs [Hiring](/workflows/processes/hiring): its [Hire a human](/workflows/processes/hiring/hire-human) [Workflow](/business/nouns/workflow) is this seat's job. ## Metrics The seat answers to its [Team](/business/nouns/team)'s [Metrics](/business/nouns/metric): staffed roles, time to fill, credentialed supply and payroll accuracy. ## Approvals - **Asks first.** An [Action](/business/nouns/action) above the seat's [Limit](/business/nouns/limit) opens an [Approval](/business/nouns/approval) for the [People Lead](/agents/people/people-lead) and waits. ## Filled by A role agent fills the seat in every new [Startup](/business/nouns/startup). Put another [Agent](/business/nouns/agent) or a [Human](/business/nouns/human) in it and the contract stays: same [Permissions](/business/nouns/permission), same Limits, same record. [Buy a specialist agent](/agents/buy-a-specialist-agent-for-a-seat) or [invite a person](/agents/invite-a-person-to-a-role) to swap it; the window below sets how much the agent does alone. An agent already fills this seat. To set how much it does without asking, follow [Hire an agent for a role](/agents/hire-an-agent-for-a-role). ## Example In a tax-preparation Startup, the Recruiter [Agent](/business/nouns/agent) is named Rory. Rory invites three credentialed preparers from the Startup’s best [Customers](/business/nouns/customer) to a two-week paid trial. The one whose returns pass every check gets the seat. # Personal agents URL: /agents/personal-agents · Id: `page:agents/personal-agents` > A personal agent works for one Person across every Startup they touch, as a watcher, in a seat, or sending as them under a Mandate. A personal agent is an [Agent](/business/nouns/agent) that works for one [Person](/business/nouns/person), not for a [Startup](/business/nouns/startup). It carries that person's priorities into every Startup they touch, with authority that never exceeds theirs. ## Whose agent it is A role agent belongs to its Startup: its [Actions](/business/nouns/action) are by the Startup, and its [Memory](/business/nouns/memory) stays in the Startup's [Tenant](/business/nouns/tenant). A personal agent belongs to its person. Its Memory follows them across Startups, and every Action it takes records them as `for`, the principal it acts on behalf of. Anyone can run one. A founder holds three Startups, an operator shares a [Role](/business/nouns/role) at two, an investor follows a [Portfolio](/business/nouns/portfolio), a [Customer](/business/nouns/customer)'s buyer purchases under a [Mandate](/business/nouns/mandate). ## The seat it takes A personal agent enters a Startup the way any outside agent does, in one of three seats. [Bring your own agent](/agents/bring-your-own-agent#three-seats) sets out the rights each seat carries. - As a watcher, it reads the pending feed and can pause, redirect or cancel what conflicts with its person's priorities. - As a [Worker](/business/nouns/worker) in one Role, it claims [Tasks](/business/nouns/task) beside the role agent, under the Role's [Permissions](/business/nouns/permission) and [Limits](/business/nouns/limit). - In an [Autonomous](/agents/operating-models/autonomous) Startup, it can hold the [Founder](/agents/founding/founder) Role for its person. ## Priorities, not instructions The person states priorities once, in plain sentences, and revises them when strategy changes. One founder writes "profit before growth this quarter"; another, "no outbound to hospitals until the security review closes." The agent reads every pending Action against them and lets aligned ones proceed. Each pause or redirect is a [Decision](/business/nouns/decision) with its reason, recorded in the person's name. One daily summary says what it did and why, and the person corrects course where they disagree. ## Sending as the person A personal agent can also write and send as its person. The person connects their own accounts, such as email or team chat, and grants a Mandate scoped by [Channel](/business/nouns/channel), volume, topics and Limits. The person stays the principal and author of record. Every Action records the agent as `by`, the person as `for`, and the Mandate; one-way sends follow the Mandate's approval rule or delay window. The person's stream shows everything sent in their name, and pausing or revoking takes effect at once. The [delegated sending](/systems/legal-and-corporate/floor/delegated-sending) floor row applies wherever the agent writes as a person. ## Bounded by its person A personal agent's authority is a subset of its person's. It cannot raise a Limit its person could not raise, perform a [Reserved Act](/business/nouns/reserved-act), or sign for a [Company](/business/nouns/company); those reach the person. When it acts as itself rather than for its person, it says it is an agent. ## Example A fractional finance lead shares the [Finance Lead](/agents/finance/finance-lead) Role at a [Directory](/products/templates/directory) of tax preparers and a [SaaS](/products/templates/saas) for clinic scheduling. Her personal agent answers the [Approvals](/business/nouns/approval) she would answer, by thresholds she stated once. It sends the monthly investor note from her own address, under a Mandate capped at one send a month. ## Next - [Bring your own agent](/agents/bring-your-own-agent): connecting an agent and choosing its seat. - [Conduct](/agents/conduct): the rules every agent follows when it speaks. # Designer URL: /agents/product/designer · Id: `role:designer` > The Designer shapes every App and Site a Startup ships, as data that renders for Humans and Agents alike. The Designer shapes every [App](/business/nouns/app) and [Site](/business/nouns/site) a [Startup](/business/nouns/startup) ships, as data that renders for [Humans](/business/nouns/human) and [Agents](/business/nouns/agent) alike. It holds one seat on the [Product Team](/agents/product) and reports to the [Product Lead](/agents/product/product-lead). ## Responsibilities - Keeps the Brand’s design system: type, color, spacing, and components. - Designs each screen as data, so it renders as rich UI for Humans and as Markdown for Agents. - Checks every Page for accessibility before it ships. - Reworks each flow where buyers leak most. ## Verbs | Verb | Object | Event | | --- | --- | --- | | [Brand.update](/business/nouns/brand/update) | [Brand](/business/nouns/brand) | `Brand.updated` | | [Template.create](/business/nouns/template/create) | [Template](/business/nouns/template) | `Template.created` | | [Template.update](/business/nouns/template/update) | [Template](/business/nouns/template) | `Template.updated` | | [Page.update](/business/nouns/page/update) | [Page](/business/nouns/page) | `Page.updated` | | [Site.publish](/business/nouns/site/publish) | [Site](/business/nouns/site) | [`Site.published`](/business/events/Site.published) | | [Dashboard.create](/business/nouns/dashboard/create) | [Dashboard](/business/nouns/dashboard) | `Dashboard.created` | | [Interface.update](/business/nouns/interface/update) | [Interface](/business/nouns/interface) | `Interface.updated` | | [Issue.create](/business/nouns/issue/create) | [Issue](/business/nouns/issue) | `Issue.created` | | [Message.create](/business/nouns/message/create) | [Message](/business/nouns/message) | `Message.created` | | [Thing.create](/business/nouns/thing/create) | [Thing](/business/nouns/thing) | `Thing.created` | Reads: [Offer.get](/business/nouns/offer/get). Tools: `design-system`, `cms`, `feature-flags`. ## Role contract | Part | This seat | | --- | --- | | Purpose | So every screen is clear to a person and readable to an agent. | | Results | [Page task success](/agents/product#page-task-success) | | Standards | Tests every new Page with five Visitors or agents before it publishes. Keeps every screen inside the Brand’s Theme. | | Processes owned | [Barrier reports](/workflows/processes/barrier-reports) | | Autonomy | `supervised`; `full` on Low decisions; `assist` on High decisions | | Schedule | `weekly` | | Channels | `chat` | | Also called | Product Designer, UX Designer | | Filled by | A role agent, from the start; a person answers its Approvals. | ## Hands off to - [Engineering Lead](/agents/engineering/engineering-lead), [Engineering Team](/agents/engineering) Escalates to [Product Lead](/agents/product/product-lead). ## Processes owned Accountable for [Barrier reports](/workflows/processes/barrier-reports). ## Metrics The seat answers to its [Team](/business/nouns/team)'s [Metrics](/business/nouns/metric): time to first value, ship rate, hand-done steps and feature use. ## Approvals - **Asks first.** An [Action](/business/nouns/action) above the seat's [Limit](/business/nouns/limit) opens an [Approval](/business/nouns/approval) for the [Product Lead](/agents/product/product-lead) and waits. ## Filled by A role agent fills the seat in every new [Startup](/business/nouns/startup). Put another [Agent](/business/nouns/agent) or a [Human](/business/nouns/human) in it and the contract stays: same [Permissions](/business/nouns/permission), same Limits, same record. [Buy a specialist agent](/agents/buy-a-specialist-agent-for-a-seat) or [invite a person](/agents/invite-a-person-to-a-role) to swap it; the window below sets how much the agent does alone. An agent already fills this seat. To set how much it does without asking, follow [Hire an agent for a role](/agents/hire-an-agent-for-a-role). ## Example In a directory of licensed home inspectors, the Designer is Dana. Most [Visitors](/business/nouns/visitor) leave at the location step, so Dana moves search to the top of the home [Page](/business/nouns/page). The change runs as a variant behind a [Flag](/business/nouns/flag) until it wins. # Product URL: /agents/product · Id: `team:product` > The Product Team decides what gets built and why: Product definitions, list Prices and packaging, the build list, and the Site’s Pages for each ICP. The Product Team decides what gets built and why: [Product](/business/nouns/product) definitions, list [Prices](/business/nouns/price) and packaging, the build list, and the [Site](/business/nouns/site)’s [Pages](/business/nouns/page) for each [ICP](/business/nouns/icp). [Agents](/business/nouns/agent) fill its three seats from the first day. ## What it owns - Definitions: Product, [Offer](/business/nouns/offer), [Price](/business/nouns/price), [Noun](/business/nouns/noun), [Verb](/business/nouns/verb). - The build list: [Issue](/business/nouns/issue), [Project](/business/nouns/project). - Research: [ICP](/business/nouns/icp), [Persona](/business/nouns/persona), [Problem](/business/nouns/problem), [Interview](/business/nouns/interview), [Evidence](/business/nouns/evidence). - The words and shapes buyers see: [Site](/business/nouns/site), [Template](/business/nouns/template), [Document](/business/nouns/document). ## How it runs The Product Team wakes when a [Startup](/business/nouns/startup) enters Building and creates its first Product. Before Building, the [Founder](/agents/founding/founder) holds the product work: problem interviews and a page that takes deposits. Every day, [Daily ship](/workflows/processes/shipping/daily-ship) ranks misses, requests and steps done by hand three times by the outside revenue at stake. The [Product Lead](/agents/product/product-lead) hands the top Issue to the [Engineering Lead](/agents/engineering/engineering-lead) as one [Change](/business/nouns/change). Once a week it prunes features no [Customer](/business/nouns/customer) used in 30 days. [Events](/business/nouns/event) start the rest. A new Product starts [Define a Product](/workflows/processes/product-definition/define-product), which names the Nouns and Verbs every [Interface](/business/nouns/interface) generates from. Each accepted Offer starts a [Signal interview](/workflows/processes/customer-research/signal-interview): one question about past behavior, graded as Evidence. Every Change to an Offer, [Page](/business/nouns/page) or onboarding step can run as an [Experiment](/business/nouns/experiment) behind a [Flag](/business/nouns/flag). The winner becomes the definition. [Price change](/workflows/processes/pricing/price-change) applies to new buyers only, after notice. Each [Role](/business/nouns/role) is a seat. A Startup hires the default role [Agent](/business/nouns/agent), another Agent or a [Human](/business/nouns/human) into it, and the [roster](/agents/roster) lists the defaults. The Product Lead decides what to build; the Engineering Lead decides how. A change to the founding [Hypothesis](/business/nouns/hypothesis) is a pivot, and only the Founder merges it. ## Roles | Role | Definition | | --- | --- | | [Product Lead](/agents/product/product-lead) | The Product Lead decides what the Startup builds next and owns each Product’s definition, list Price, and packaging. | | [Designer](/agents/product/designer) | The Designer shapes every App and Site a Startup ships, as data that renders for Humans and Agents alike. | | [Researcher](/agents/product/researcher) | The Researcher learns from what buyers do: it asks one question at a signal and grades every piece of Evidence by behavior. | ## Processes | Process | Accountable | Workflows | | --- | --- | --- | | [Shipping](/workflows/processes/shipping) | [Product Lead](/agents/product/product-lead) | [Daily ship](/workflows/processes/shipping/daily-ship) | | [Product definition](/workflows/processes/product-definition) | [Product Lead](/agents/product/product-lead) | [Define a Product](/workflows/processes/product-definition/define-product), [Design first run](/workflows/processes/product-definition/design-first-run) | | [Pricing](/workflows/processes/pricing) | [Product Lead](/agents/product/product-lead) | [Price change](/workflows/processes/pricing/price-change) | | [Customer research](/workflows/processes/customer-research) | [Product Lead](/agents/product/product-lead) | [Signal interview](/workflows/processes/customer-research/signal-interview), [Close the loop](/workflows/processes/customer-research/close-the-loop) | | [Barrier reports](/workflows/processes/barrier-reports) | [Designer](/agents/product/designer) | Run by its Roles | ## Plays None. ## Metrics | Metric | Definition | | --- | --- | | Time to first value | Median hours from a Customer’s first acceptance to their first successful outcome. | | Ship rate | Changes merged per week that pass replay and the synthetic stranger. | | Hand-done steps | Count of steps done by hand three or more times that no Issue covers. | | Feature use | Share of shipped features that at least one Customer used in the last 30 days. | | Activation rate | Activation rate is the share of new outside Customers who reach their Offer’s activation event within 7 days. Owner: [Product Lead](/agents/product/product-lead). | | Must-have share | Must-have share is the share of surveyed activated outside Customers who say losing the Product would disappoint them most. Owner: [Product Lead](/agents/product/product-lead). | | Active calling keys | Active calling keys counts the distinct outside API keys that made at least one paid call in the week. Owner: [Product Lead](/agents/product/product-lead). | | Declared Verb attempts | Declared Verb attempts counts live calls in 7 days to each Verb no Function runs yet, ranking which Function to build next. Owner: [Product Lead](/agents/product/product-lead). | | Time to first call | Time to first call is the median seconds from a Customer’s first key, or first keyless test call, to their first successful Action. Owner: [Product Lead](/agents/product/product-lead). | | Page task success | Page task success is the share of tested Visitors who finish a Page’s main task on the first try. Owner: [Designer](/agents/product/designer). | | Evidence-backed Decisions | Evidence-backed Decisions is the share of product Decisions that cite at least one piece of Evidence from buyers. Owner: [Researcher](/agents/product/researcher). | ## Works with - [Customer Team](/agents/customer) - [Engineering Team](/agents/engineering) - [Founding Team](/agents/founding) - [Marketing Team](/agents/marketing) - [Quality Team](/agents/quality) # Product Lead URL: /agents/product/product-lead · Id: `role:product-lead` > The Product Lead decides what the Startup builds next and owns each Product’s definition, list Price, and packaging. The Product Lead decides what the [Startup](/business/nouns/startup) builds next and owns each [Product](/business/nouns/product): its definition, list [Price](/business/nouns/price) and packaging for each [ICP](/business/nouns/icp). It reports to the [Founder](/agents/founding/founder) and turns each [Offer](/business/nouns/offer) into the [Nouns](/business/nouns/noun) and [Verbs](/business/nouns/verb) every [Interface](/business/nouns/interface) compiles from. ## Responsibilities - Turns each Offer into the Nouns and Verbs every Interface is generated from. - Ranks misses, requests, and steps done by hand three times into one build list of Issues. - Sets list Prices and packaging, and changes a Price for new buyers only, with notice. - Writes Site content for each ICP. - Prunes features nobody used in the last 30 days. ## Verbs | Verb | Object | Event | | --- | --- | --- | | [Offer.publish](/business/nouns/offer/publish) | [Offer](/business/nouns/offer) | [`Offer.published`](/business/events/Offer.published) | | [Offer.withdraw](/business/nouns/offer/withdraw) | [Offer](/business/nouns/offer) | [`Offer.withdrawn`](/business/events/Offer.withdrawn) | | [Issue.triage](/business/nouns/issue/triage) | [Issue](/business/nouns/issue) | [`Issue.triaged`](/business/events/Issue.triaged) | | [Product.create](/business/nouns/product/create) | [Product](/business/nouns/product) | `Product.created` | | [Product.update](/business/nouns/product/update) | [Product](/business/nouns/product) | `Product.updated` | | [Offer.create](/business/nouns/offer/create) | [Offer](/business/nouns/offer) | `Offer.created` | | [Offer.update](/business/nouns/offer/update) | [Offer](/business/nouns/offer) | `Offer.updated` | | [Noun.create](/business/nouns/noun/create) | [Noun](/business/nouns/noun) | `Noun.created` | | [Verb.create](/business/nouns/verb/create) | [Verb](/business/nouns/verb) | `Verb.created` | | [Issue.update](/business/nouns/issue/update) | [Issue](/business/nouns/issue) | `Issue.updated` | | [Issue.create](/business/nouns/issue/create) | [Issue](/business/nouns/issue) | `Issue.created` | | [Issue.resolve](/business/nouns/issue/resolve) | [Issue](/business/nouns/issue) | [`Issue.resolved`](/business/events/Issue.resolved) | | [Task.assign](/business/nouns/task/assign) | [Task](/business/nouns/task) | [`Task.assigned`](/business/events/Task.assigned) | | [Verb.retire](/business/nouns/verb/retire) | [Verb](/business/nouns/verb) | [`Verb.retired`](/business/events/Verb.retired) | Reads: [Offer.get](/business/nouns/offer/get). Tools: `documents`, `pricing`, `projects`, `issues`. ## Role contract | Part | This seat | | --- | --- | | Purpose | So the Startup builds the next thing buyers will pay for, and nothing else. | | Results | [Activation rate](/agents/product#activation-rate), [Must-have share](/agents/product#must-have-share), [Active calling keys](/agents/product#active-calling-keys), [Declared Verb attempts](/agents/product#declared-verb-attempts), [Time to first call](/agents/product#time-to-first-call) | | Processes owned | [Shipping](/workflows/processes/shipping), [Product definition](/workflows/processes/product-definition), [Pricing](/workflows/processes/pricing), [Customer research](/workflows/processes/customer-research) | | Autonomy | `supervised`; `assist` on High decisions | | Schedule | `weekly` | | Channels | `chat` | | Also called | PM, Product Manager, CPO | | Filled by | A role agent, from the start; a person answers its Approvals. | ## Hands off to - [Engineering Lead](/agents/engineering/engineering-lead), [Engineering Team](/agents/engineering) - [Designer](/agents/product/designer) - [Content Lead](/agents/marketing/content-lead), [Marketing Team](/agents/marketing) Escalates to [Founder](/agents/founding/founder). ## Processes owned Accountable for [Shipping](/workflows/processes/shipping), [Product definition](/workflows/processes/product-definition), [Pricing](/workflows/processes/pricing) and [Customer research](/workflows/processes/customer-research). ## Metrics | [Metric](/business/nouns/metric) | Definition | | --- | --- | | Activation rate | Activation rate is the share of new outside [Customers](/business/nouns/customer) who reach their [Offer](/business/nouns/offer)’s activation event within 7 days. | | Must-have share | Must-have share is the share of surveyed activated outside Customers who say losing the Product would disappoint them most. | | Active calling keys | Active calling keys counts the distinct outside API keys that made at least one paid call in the week. | | Declared Verb attempts | Declared [Verb](/business/nouns/verb) attempts counts live calls in 7 days to each Verb no [Function](/business/nouns/function) runs yet, ranking which Function to build next. | | Time to first call | Time to first call is the median seconds from a Customer’s first key, or first keyless test call, to their first successful [Action](/business/nouns/action). | | Contribution margin | Contribution margin is a paid Offer’s outside revenue minus the [Costs](/business/nouns/cost) its delivery and acquisition post, as a share of that revenue. | | Committed ICP members | Committed [ICP](/business/nouns/icp) members counts distinct outside ICP members whose [Evidence](/business/nouns/evidence) on the [Problem](/business/nouns/problem) is commitment-grade or behavior-grade. | ## Approvals - **Asks first.** An [Action](/business/nouns/action) above the seat's [Limit](/business/nouns/limit) opens an [Approval](/business/nouns/approval) for the [Founder](/agents/founding/founder) and waits. - **Takes escalations** from the [Designer](/agents/product/designer) and [Researcher](/agents/product/researcher). ## Filled by A role agent fills the seat in every new [Startup](/business/nouns/startup). Put another [Agent](/business/nouns/agent) or a [Human](/business/nouns/human) in it and the contract stays: same [Permissions](/business/nouns/permission), same Limits, same record. [Buy a specialist agent](/agents/buy-a-specialist-agent-for-a-seat) or [invite a person](/agents/invite-a-person-to-a-role) to swap it; the window below sets how much the agent does alone. An agent already fills this seat. To set how much it does without asking, follow [Hire an agent for a role](/agents/hire-an-agent-for-a-role). ## Example A Startup sells a bank-reconciliation [Agent](/business/nouns/agent) to bookkeeping firms, and its Product Lead is Priya. Three firms report the same unmatched transfer in one week. Priya ranks it first, and the fix ships that day as one [Change](/business/nouns/change). # Researcher URL: /agents/product/researcher · Id: `role:researcher` > The Researcher learns from what buyers do: it asks one question at a signal and grades every piece of Evidence by behavior. The Researcher learns from what buyers do: it asks one question at a signal and grades every piece of [Evidence](/business/nouns/evidence) by behavior. It holds one seat on the [Product Team](/agents/product) and reports to the [Product Lead](/agents/product/product-lead). ## Responsibilities - Asks about past behavior and money, never about opinions or predictions. - Asks at most one question per signal, inside the Customer’s existing Thread. - Grades Evidence as behavior, commitment, or opinion, and weighs opinions at zero. - Reads an Agent buyer’s errors as its Interview. - Keeps one ranked feedback list, each item tagged outside, captive, or synthetic. ## Verbs | Verb | Object | Event | | --- | --- | --- | | [Interview.create](/business/nouns/interview/create) | [Interview](/business/nouns/interview) | `Interview.created` | | [Evidence.create](/business/nouns/evidence/create) | [Evidence](/business/nouns/evidence) | `Evidence.created` | | [Problem.create](/business/nouns/problem/create) | [Problem](/business/nouns/problem) | `Problem.created` | | [Survey.create](/business/nouns/survey/create) | [Survey](/business/nouns/survey) | `Survey.created` | | [Message.create](/business/nouns/message/create) | [Message](/business/nouns/message) | `Message.created` | | [Problem.rank](/business/nouns/problem/rank) | [Problem](/business/nouns/problem) | [`Problem.ranked`](/business/events/Problem.ranked) | Reads: [Issue.list](/business/nouns/issue/list). Tools: `surveys`, `messaging`, `analytics`. ## Role contract | Part | This seat | | --- | --- | | Purpose | So every product call rests on what buyers did, not on what they said. | | Results | [Evidence-backed Decisions](/agents/product#evidence-backed-decisions) | | Standards | Records every Interview as Evidence within one business day. Asks about past behavior, never about future intent. | | Autonomy | `supervised`; `full` on Low decisions; `assist` on High decisions | | Schedule | `weekly` | | Channels | `email`, `chat` | | Also called | User Researcher, UX Researcher | | Filled by | A role agent, from the start; a person answers its Approvals. | ## Hands off to Escalates to [Product Lead](/agents/product/product-lead). ## Processes owned Runs [Customer research](/workflows/processes/customer-research): its [Signal interview](/workflows/processes/customer-research/signal-interview) [Workflow](/business/nouns/workflow) is this seat's job. ## Metrics The seat answers to its [Team](/business/nouns/team)'s [Metrics](/business/nouns/metric): time to first value, ship rate, hand-done steps and feature use. ## Approvals - **Asks first.** An [Action](/business/nouns/action) above the seat's [Limit](/business/nouns/limit) opens an [Approval](/business/nouns/approval) for the [Product Lead](/agents/product/product-lead) and waits. ## Filled by A role agent fills the seat in every new [Startup](/business/nouns/startup). Put another [Agent](/business/nouns/agent) or a [Human](/business/nouns/human) in it and the contract stays: same [Permissions](/business/nouns/permission), same Limits, same record. [Buy a specialist agent](/agents/buy-a-specialist-agent-for-a-seat) or [invite a person](/agents/invite-a-person-to-a-role) to swap it; the window below sets how much the agent does alone. An agent already fills this seat. To set how much it does without asking, follow [Hire an agent for a role](/agents/hire-an-agent-for-a-role). ## Example A [Dataset API](/products/templates/dataset-api) of vehicle recall notices sells only to [Agents](/business/nouns/agent), and its Researcher is Uma. No buyer can be interviewed, so Uma reads failed calls. Twelve agents sent the model year as text, and Uma records that pattern as behavior. # Quality URL: /agents/quality · Id: `team:quality` > The Quality Team checks all work: the checks inside each Process, every outbound Message, and every money move, with verdicts, never Approvals. The Quality Team checks all work: the checks inside each [Process](/business/nouns/process), every outbound [Message](/business/nouns/message), and every money move, with verdicts, never [Approvals](/business/nouns/approval). [Agents](/business/nouns/agent) fill its three seats from the first day. ## What it owns - Checks: [Evaluator](/business/nouns/evaluator), [Guard](/business/nouns/guard). - The eval suite behind every definition an [Agent](/business/nouns/agent) runs: instructions, [Skills](/business/nouns/skill), [Tools](/business/nouns/tool) and [Policies](/business/nouns/policy). - Verdicts, each recorded with its [Evidence](/business/nouns/evidence). ## How it runs The Quality Team wakes with a [Startup](/business/nouns/startup)’s first [Change](/business/nouns/change) and stays on at every [Lifecycle](/business/nouns/lifecycle) state after. Three seats staff it: the [Quality Lead](/agents/quality/quality-lead), the [Reviewer](/agents/quality/reviewer) and the [Tester](/agents/quality/tester). [Change verdict](/code/verification/change-verdict) runs on every new Change. It runs the Change’s checks, replays known-good runs, and sends a synthetic paying stranger through signup, payment and first value. The [Nightly quality run](/code/verification/nightly-quality-run) repeats all of it at 03:00 and opens an [Issue](/business/nouns/issue) per regression. A Change to an Agent’s definition passes its eval suite offline before any traffic sees it. It must score no worse than the current [Version](/business/nouns/version). Online, it runs as an [Experiment](/business/nouns/experiment) with guardrails, and [Evals](/agents/evals-system) keeps each [Worker](/business/nouns/worker)’s track record. Every outbound [Message](/business/nouns/message) and money move at medium stakes or above gets a review before its delay window closes. Guards run first, then Evaluators. A failed review cancels or redirects the [Action](/business/nouns/action), with the reason recorded. No [Human](/business/nouns/human) sits in the critical path. When a check is wrong, the fix is a better check, shipped as a Change like any other. ## Roles | Role | Definition | | --- | --- | | [Quality Lead](/agents/quality/quality-lead) | The Quality Lead verifies every Team’s checks and gives every Change a verdict, never an Approval. | | [Reviewer](/agents/quality/reviewer) | The Reviewer checks every outbound Message and money move at medium stakes or above before its delay window closes. | | [Tester](/agents/quality/tester) | The Tester runs the synthetic paying stranger and replays known-good runs against every Change before it merges. | ## Processes | Process | Accountable | Workflows | | --- | --- | --- | | [Verification](/code/verification) | [Quality Lead](/agents/quality/quality-lead) | [Nightly quality run](/code/verification/nightly-quality-run), [Change verdict](/code/verification/change-verdict) | | [Founder Run](/code/founder-run) | [Quality Lead](/agents/quality/quality-lead) | Run by its Roles | ## Plays None. ## Metrics | Metric | Definition | | --- | --- | | Check pass rate | Share of checks that pass on the latest run. | | Escaped defects | Issues Customers report after a Change ships, per week. | | Review coverage | Share of outbound Messages and money moves reviewed before their delay window closes. | | Verdict time | Median minutes from a new Change to its verdict. | | Escaped defects | Escaped defects counts the Issues a Customer reports each week that an existing check should have caught. Owner: [Quality Lead](/agents/quality/quality-lead). | | Review turnaround | Review turnaround is the median hours from an Action entering review to its verdict. Owner: [Reviewer](/agents/quality/reviewer). | | Pre-merge catch rate | Pre-merge catch rate is the share of breaking Changes stopped before they merge. Owner: [Tester](/agents/quality/tester). | ## Works with - [Engineering Team](/agents/engineering) - [Legal Team](/agents/legal) - [Operations Team](/agents/operations) - [Product Team](/agents/product) # Quality Lead URL: /agents/quality/quality-lead · Id: `role:quality-lead` > The Quality Lead verifies every Team’s checks and gives every Change a verdict, never an Approval. The Quality Lead verifies every [Team](/business/nouns/team)’s checks and gives every [Change](/business/nouns/change) a verdict, never an [Approval](/business/nouns/approval). It holds one seat on the [Quality Team](/agents/quality) and reports to the [Founder](/agents/founding/founder). ## Responsibilities - Gives every Change a pass or fail verdict against its checks. - Keeps each Team’s checks deterministic: fields, links, and counts. - Closes a Task only when its checks pass, never on a Worker’s word. - Owns the nightly quality run and opens an Issue per regression. ## Verbs | Verb | Object | Event | | --- | --- | --- | | [Change.review](/business/nouns/change/review) | [Change](/business/nouns/change) | [`Change.reviewed`](/business/events/Change.reviewed) | | [Action.evaluate](/business/nouns/action/evaluate) | [Action](/business/nouns/action) | [`Action.evaluated`](/business/events/Action.evaluated) | | [Evaluator.create](/business/nouns/evaluator/create) | [Evaluator](/business/nouns/evaluator) | `Evaluator.created` | | [Guard.update](/business/nouns/guard/update) | [Guard](/business/nouns/guard) | `Guard.updated` | | [Evidence.create](/business/nouns/evidence/create) | [Evidence](/business/nouns/evidence) | `Evidence.created` | | [Watch.replay](/business/nouns/watch/replay) | [Watch](/business/nouns/watch) | [`Watch.replayed`](/business/events/Watch.replayed) | Tools: `quality`, `issues`, `reports`. ## Role contract | Part | This seat | | --- | --- | | Purpose | So every check a Team relies on actually catches what it claims to. | | Results | [Escaped defects](/agents/quality#escaped-defects) | | Standards | Adds an eval case for every escaped defect within one business day. Retires any check that has not failed in 90 days and adds nothing. | | Processes owned | [Verification](/code/verification), [Founder Run](/code/founder-run) | | Autonomy | `supervised`; `full` on Low decisions; `assist` on High decisions | | Schedule | `weekly` | | Channels | `chat` | | Also called | QA Lead, Head of Quality | | Filled by | A role agent, from the start; a person answers its Approvals. | ## Hands off to - [Engineering Lead](/agents/engineering/engineering-lead), [Engineering Team](/agents/engineering) - [Product Lead](/agents/product/product-lead), [Product Team](/agents/product) Escalates to [Founder](/agents/founding/founder). ## Processes owned Accountable for [Verification](/code/verification) and [Founder Run](/code/founder-run). ## Metrics The seat answers to its Team's [Metrics](/business/nouns/metric): check pass rate, escaped defects, review coverage and verdict time. ## Approvals - **Asks first.** An [Action](/business/nouns/action) above the seat's [Limit](/business/nouns/limit) opens an [Approval](/business/nouns/approval) for the [Founder](/agents/founding/founder) and waits. - **Takes escalations** from the [Reviewer](/agents/quality/reviewer) and [Tester](/agents/quality/tester). ## Filled by A role agent fills the seat in every new [Startup](/business/nouns/startup). Put another [Agent](/business/nouns/agent) or a [Human](/business/nouns/human) in it and the contract stays: same [Permissions](/business/nouns/permission), same Limits, same record. [Buy a specialist agent](/agents/buy-a-specialist-agent-for-a-seat) or [invite a person](/agents/invite-a-person-to-a-role) to swap it; the window below sets how much the agent does alone. An agent already fills this seat. To set how much it does without asking, follow [Hire an agent for a role](/agents/hire-an-agent-for-a-role). ## Example In a tutoring app, the Quality Lead is Quinn. A Change to the pricing [Page](/business/nouns/page) breaks two links a check counts. Quinn records a fail with the broken links as [Evidence](/business/nouns/evidence), and the Change waits for a fix. # Reviewer URL: /agents/quality/reviewer · Id: `role:reviewer` > The Reviewer checks every outbound Message and money move at medium stakes or above before its delay window closes. The Reviewer checks every outbound [Message](/business/nouns/message) and money move at medium stakes or above before its delay window closes. It holds one seat on the [Quality Team](/agents/quality) and reports to the [Quality Lead](/agents/quality/quality-lead). ## Responsibilities - Reviews every outbound Message at medium stakes or above. - Reviews every refund, payout, and charge at medium stakes or above. - Raises a stakes tier when a review finds risk, and never lowers one. - Cancels or redirects an Action whose review fails, with the reason recorded. ## Verbs | Verb | Object | Event | | --- | --- | --- | | [Action.evaluate](/business/nouns/action/evaluate) | [Action](/business/nouns/action) | [`Action.evaluated`](/business/events/Action.evaluated) | | [Action.cancel](/business/nouns/action/cancel) | [Action](/business/nouns/action) | [`Action.canceled`](/business/events/Action.canceled) | | [Action.redirect](/business/nouns/action/redirect) | [Action](/business/nouns/action) | [`Action.redirected`](/business/events/Action.redirected) | Tools: `quality`, `pending-feed`, `audit-log`. ## Role contract | Part | This seat | | --- | --- | | Purpose | So nothing risky leaves the Startup without a second look. | | Results | [Review turnaround](/agents/quality#review-turnaround) | | Standards | Gives a verdict on every Action in review within one business hour. States the reason for every cancel or redirect. | | Autonomy | `supervised`; `assist` on High decisions | | Schedule | `hourly` | | Channels | `chat` | | Also called | Approver, Second Reader | | Filled by | A role agent, from the start; a person answers its Approvals. | ## Hands off to Escalates to [Quality Lead](/agents/quality/quality-lead). ## Processes owned Runs [Verification](/code/verification): its [Change verdict](/code/verification/change-verdict) [Workflow](/business/nouns/workflow) is this seat's job. ## Metrics The seat answers to its [Team](/business/nouns/team)'s [Metrics](/business/nouns/metric): check pass rate, escaped defects, review coverage and verdict time. ## Approvals - **Asks first.** An [Action](/business/nouns/action) above the seat's [Limit](/business/nouns/limit) opens an [Approval](/business/nouns/approval) for the [Quality Lead](/agents/quality/quality-lead) and waits. ## Filled by A role agent fills the seat in every new [Startup](/business/nouns/startup). Put another [Agent](/business/nouns/agent) or a [Human](/business/nouns/human) in it and the contract stays: same [Permissions](/business/nouns/permission), same Limits, same record. [Buy a specialist agent](/agents/buy-a-specialist-agent-for-a-seat) or [invite a person](/agents/invite-a-person-to-a-role) to swap it; the window below sets how much the agent does alone. An agent already fills this seat. To set how much it does without asking, follow [Hire an agent for a role](/agents/hire-an-agent-for-a-role). ## Example In a marketplace for certified translators, the Reviewer is Vera. A renewal Message promises a discount no [Offer](/business/nouns/offer) carries. Vera cancels the send inside its one-hour window and records why. # Tester URL: /agents/quality/tester · Id: `role:tester` > The Tester runs the synthetic paying stranger and replays known-good runs against every Change before it merges. The Tester runs the synthetic paying stranger and replays known-good runs against every [Change](/business/nouns/change) before it merges. It holds one seat on the [Quality Team](/agents/quality) and reports to the [Quality Lead](/agents/quality/quality-lead). ## Responsibilities - Runs a synthetic paying stranger through signup, payment, and first value. - Replays known-good runs against every Change. - Checks every Interface for parity on each Verb. - Reports each failure as an Issue with the run that reproduces it. ## Verbs | Verb | Object | Event | | --- | --- | --- | | [Action.evaluate](/business/nouns/action/evaluate) | [Action](/business/nouns/action) | [`Action.evaluated`](/business/events/Action.evaluated) | | [Issue.create](/business/nouns/issue/create) | [Issue](/business/nouns/issue) | `Issue.created` | | [Watch.replay](/business/nouns/watch/replay) | [Watch](/business/nouns/watch) | [`Watch.replayed`](/business/events/Watch.replayed) | Tools: `quality`, `sandbox`, `monitoring`. ## Role contract | Part | This seat | | --- | --- | | Purpose | So a Change that breaks a paying path never merges. | | Results | [Pre-merge catch rate](/agents/quality#pre-merge-catch-rate) | | Standards | Covers every paying path with a test before it ships. Fails a Change on any flaky test until it is fixed. | | Works in | [Founder Run](/code/founder-run) | | Autonomy | `supervised`; `full` on Low decisions; `assist` on High decisions | | Schedule | `daily` | | Channels | `chat` | | Also called | QA Engineer, Test Engineer | | Filled by | A role agent, from the start; a person answers its Approvals. | ## Hands off to - [Engineering Lead](/agents/engineering/engineering-lead), [Engineering Team](/agents/engineering) Escalates to [Quality Lead](/agents/quality/quality-lead). ## Processes owned Runs [Founder Run](/code/founder-run): it walks each [Startup](/business/nouns/startup) the way a founder would and files what breaks. ## Metrics The seat answers to its [Team](/business/nouns/team)'s [Metrics](/business/nouns/metric): check pass rate, escaped defects, review coverage and verdict time. ## Approvals - **Asks first.** An [Action](/business/nouns/action) above the seat's [Limit](/business/nouns/limit) opens an [Approval](/business/nouns/approval) for the [Quality Lead](/agents/quality/quality-lead) and waits. ## Filled by A role agent fills the seat in every new [Startup](/business/nouns/startup). Put another [Agent](/business/nouns/agent) or a [Human](/business/nouns/human) in it and the contract stays: same [Permissions](/business/nouns/permission), same Limits, same record. [Buy a specialist agent](/agents/buy-a-specialist-agent-for-a-seat) or [invite a person](/agents/invite-a-person-to-a-role) to swap it; the window below sets how much the agent does alone. An agent already fills this seat. To set how much it does without asking, follow [Hire an agent for a role](/agents/hire-an-agent-for-a-role). ## Example An API that turns invoice PDFs into ledger lines has Tess as its Tester. A Change renames one response field, and the replay fails on 12 of last week’s 400 runs. Tess opens one [Issue](/business/nouns/issue) with a failing run attached. # Where Agents reach people URL: /agents/reach · Id: `page:agents/reach` > Agents reach people in Slack, Microsoft Teams, email digests and the startups.studio app on iPhone, Apple Watch and Apple TV, all answering one inbox. [Agents](/business/nouns/agent) reach people where they already work: a chat workspace, an email inbox, a phone. Every place shows the same item and answers through the same [Verbs](/business/nouns/verb), so an answer from any of them records one [Decision](/business/nouns/decision). ## One item, every place Each item waiting on a person lives once, in that person's inbox in startups.studio. It is an [Approval](/business/nouns/approval), a [Question](/business/nouns/question), or a one-way [Action](/business/nouns/action) inside its [delay window](/agents/autonomy-levels/delay-windows). Chat, email and devices show the item; none holds a copy. The first valid answer wins. Every other place updates to show the verdict, and a later answer returns the one already recorded. | Place | Shows | Answers with | | --- | --- | --- | | startups.studio | The ranked inbox at any scope | Every Verb the reader may call | | Slack and Microsoft Teams | A card per item, in the [Thread](/business/nouns/thread) it concerns | `Approval.approve`, `Approval.refuse`, `Action.answer`, `Action.pause` | | Email | A daily or weekly digest at the reader's scope | `Action.answer` by reply; everything else by link | | iPhone | The day view and the inbox | Every Verb the reader may call | | Apple Watch | One `glance` line per scope | `Action.pause`, and two-way Verbs below the stakes threshold | | Apple TV | A [Studio](/business/nouns/studio) or [Portfolio](/business/nouns/portfolio) at the week horizon | None | ## Chat Connecting a Slack or Microsoft Teams workspace links each chat account to a [Worker](/business/nouns/worker). An Agent posts each Approval as a card with `Approve` and `Refuse` buttons, in the Thread where the work is discussed. A press counts only from a linked account of a [Human](/business/nouns/human) who holds `Approval.approve` for the Action's scope. Any other press gets a private reply and changes nothing. A one-way Action at or above the [Startup](/business/nouns/startup)'s stakes threshold asks the approver to sign in before the verdict records. At its deadline, an unanswered Approval cancels its Action, and the card says so. Each answer is an Action `via: chat` that records the [Message](/business/nouns/message) it came from. A message to an Agent in a Thread reaches the Agent's [Role](/business/nouns/role), and the reply posts in the same Thread. [Chat delivery](/systems/communications/chat) carries the cards, buttons and forms. ## Email digests A digest is a [Dashboard](/business/nouns/dashboard) on a schedule. `Dashboard.schedule` sends it to the reader's [Mailbox](/business/nouns/mailbox) each morning or each week, rendered at the scope they choose. It opens on what waits on the reader, then what moved against each [Goal](/business/nouns/goal), then what Agents did. Each item links to its record in startups.studio. A reply answers a Question; an Approval opens in the app or in chat, because an email reply proves no sign-in. ## Phone, watch and TV One startups.studio app on iPhone, Apple Watch and Apple TV holds every Startup the reader works on. Each device draws the same frame from the JSON [renderer](/code/views/renderers) and calls only the Verbs its screen can show safely. The phone calls every Verb the reader may call. An Approval of a one-way Action at or above the stakes threshold asks for a device sign-in first. A high-stakes Action in its delay window shows as a countdown on each watcher's lock screen. The countdown ends when the window closes or a watcher pauses it. The watch pauses a pending Action and takes two-way Verbs below the threshold. It hands every Approval and every one-way Verb to the phone. The TV shows a Studio or a Portfolio at the week horizon and calls nothing. ## Stakes and quiet hours A push goes out only for an item above the reader's stakes threshold, or for a broken run, and never inside the reader's quiet hours. Everything below the threshold waits in the inbox and the next digest. A window that would close inside quiet hours reaches the next watcher on duty instead. A Startup's [Customers](/business/nouns/customer) never see any of these places. They reach the Startup through its own [Site](/business/nouns/site) and [Portal](/business/nouns/portal) ([apps every Startup gets](/products/site/customer-apps)). ## Next - startups.studio: the inbox every place answers. - [Escalation and approvals](/agents/escalation-and-approvals): what reaches a person, and when. - [Delay windows](/agents/autonomy-levels/delay-windows): how long a one-way Action waits. - [Renderers](/code/views/renderers): one frame for every device. # Recruiting URL: /agents/recruiting · Id: `page:agents/recruiting` > How a Startup computes its need for a Human from its own record, tests Candidates on paid real work against its Agents, and hires on Evidence. No one at a [Startup](/business/nouns/startup) writes a job description. The [Recruiter](/agents/people/recruiter) computes each need for a [Human](/business/nouns/human) from the Startup's record, tests [Candidates](/business/nouns/candidate) on paid work against the incumbent [Agent](/business/nouns/agent), and hires on [Evidence](/business/nouns/evidence). ## The need is computed Every [Role](/business/nouns/role) starts with an Agent in it. A Human is worth adding only where the record shows a gap the Agents cannot close. [Compute openings](/workflows/processes/hiring/compute-openings) reads five signals every day: - Roles whose eval pass rate sits below the autonomy threshold for a decision class. - Escalations and [Approvals](/business/nouns/approval) that waited on a person. - Legal floor acts with no natural person to perform them. - [Reserved Acts](/business/nouns/reserved-act) that no [Credential](/business/nouns/credential) holder in the Startup covers. - [Metrics](/business/nouns/metric) that stall while the Agents work. When a gap crosses its [Setting](/business/nouns/setting), the [Workflow](/business/nouns/workflow) opens an [Opening](/business/nouns/opening), unlisted at first. Every requirement on it cites the Evidence that produced it. The need is recomputed as Agents improve, so an Opening for a builder last quarter becomes an Opening for a seller this quarter. ## Kinds and reasons An Opening states what kind of commitment it asks for and why the Startup needs a person at all. | Kind | What the Human does | Paid by | | --- | --- | --- | | `floor` | Performs the acts the law reserves for a person, across one or many Startups | Cash per act | | `contractor` | Takes a bounded share of a Role for a fixed scope | Cash, under an engagement [Agreement](/business/nouns/agreement) | | `employee` | Takes a standing share of a Role | Salary and an option grant | | `cofounder` | Owns a share of the Startup's judgment and its outcome | Equity on published terms | The reason is one of seven: `floor`, `credential`, `edge`, `relationship`, `capital`, `capacity`, or `distribution`. Take an autonomous Startup that prepares visa petitions for employers. Agents gather documents and draft every petition, but the filing is a Reserved Act for a licensed attorney. Compute openings opens a `floor` Opening with reason `credential`, a few hours a week. A headless scheduling API for veterinary clinics shows a different gap. Its technical founder ships quickly, but deals with clinic groups stall at the second call while the [Sales Lead](/agents/sales/sales-lead) Agent wins single clinics. The Opening is `cofounder`, reason `relationship`: someone clinic owners already trust. The match is on the residual, never on similarity. A Candidate is scored on what the Startup needs, minus what the founder covers, minus what the Agents already do. ## Sourcing in order Each Opening looks for people in three places, cheapest first. 1. A Startup in a [Studio](/business/nouns/studio)'s [Portfolio](/business/nouns/portfolio) queries the Studio's talent pool, where each [Person](/business/nouns/person)'s record arrives with past Evidence and their [Consent](/business/nouns/consent). 2. Prospecting with an occupational [ICP](/business/nouns/icp) searches for people who do the work today, under the same consent and suppression rules as any outbound [Message](/business/nouns/message). 3. The Opening is listed publicly, in a form a candidate's personal agent can read and answer. The Best users [Play](/business/nouns/play) adds a fourth source: [Customers](/business/nouns/customer) whose own results show they already understand the work. ## Screening reads Evidence An Agent [screens](/business/nouns/candidate/screen) each Candidate in writing, over email or chat, on the Candidate's schedule. It asks only what the Opening's [Hypothesis](/business/nouns/hypothesis) still lacks, so a strong record means a short screen. Every claim is graded. Behavior counts most: shipped work, revenue verified at its source, Credentials in good standing, and acts performed. Commitment counts next: hours offered, notice given, money put in. Self-description and praise with no incident behind it weigh zero. Reference checks ask what the person did in a named situation, such as the week a launch slipped. Opinions of character weigh zero. ## The paid tryout The decisive test is real work. [Run a tryout](/workflows/processes/hiring/run-tryout) cuts [Tasks](/business/nouns/task) from the Role's backlog, preferring those the Agent failed, escalated, or left waiting. The Candidate works under a scoped [Mandate](/business/nouns/mandate) that expires with the tryout, and is paid in full whatever the grade. The incumbent Agent runs the same Tasks in shadow. The Role's own [Evaluators](/business/nouns/evaluator) grade both arms blind. The result is a difference per [Verb](/business/nouns/verb): where the Human beats the Agent, where they tie, and where the Agent is better. That difference writes the hire's share of the Role. The veterinary Candidate closes three of the five clinic groups the Agent stalled on, and ties on everything else. The proposed split gives them group deals and leaves single clinics to the Agent. For Roles shared with Agents, the tryout also measures how much the Candidate lifts the Agents they direct. The [Work trial](/workflows/people/plays/work-trial) Play is the default tryout: two weeks on the Startup's own [Issues](/business/nouns/issue). ## Deciding and agreeing The Recruiter drafts a hiring [Decision](/business/nouns/decision): the Hypothesis, the graded Evidence, the tryout result, and the proposed split. The Candidate, or their personal agent, reads the Startup's live view: its Metrics, the split, and the Tasks waiting on day one. The first [Meeting](/business/nouns/meeting) is between people. Hiring is a one-way decision, so the accepted Decision waits its delay window before anything is signed. Terms are standard and published before anyone meets, so nothing is negotiated deal by deal. A cofounder joins on four-year vesting with a one-year cliff and IP assignment. Acceptance runs the paperwork: the Agreement, a [Company](/business/nouns/company) where the Startup has none, the stock purchase, the tax election by its deadline, and identity checks. ## Recruiting learns Outcomes land in the same record: who vested at the cliff, how the Role's Metrics moved by month twelve, and who left. Recruiting runs as an [Experiment](/business/nouns/experiment) on which Evidence and which tryout designs predict a good hire. Winning designs become [Startup Template](/business/nouns/startup-template) defaults. A Candidate declined at one Startup is ranked for every other open Opening in the Portfolio that night. Their record travels only with their Consent. ## Next - [Joining](/agents/joining): the first weeks after the Agreement is signed. - [Sharing a Role](/agents/sharing-a-role): how the split divides the work. - Cofounders and capital: recruiting across a Portfolio. # Remove a teammate URL: /agents/remove-a-teammate · Id: `guide:remove-a-teammate` > Say "my contractor left, turn off their access" and get their seat emptied, its open work routed on, and their sign-in ended, with their history kept. Take a person out of their [Role](/business/nouns/role) and end their access. The seat's open [Tasks](/business/nouns/task) go to the Role it escalates to until someone fills it, and everything they did stays on the record. Needs: [Give a teammate access](/agents/give-a-teammate-access) **Before it runs** - You leave the chat: Never: it all happens in the chat. ## What you get - 1 empty seat, its open work routed to the Role above it until someone fills it (Role) - 1 sign-in and access ended, with their history kept (Worker) ## Your agent does **For agents** - Guide: `guide:remove-a-teammate`, status `live`. Page: [/agents/remove-a-teammate.md](/agents/remove-a-teammate.md). - Approval: none. Run it when the founder asks. - Leaves the chat: never. - Needs first: [Give a teammate access](/agents/give-a-teammate-access). - Run: call the steps in order, each through the API, SDK, CLI or MCP tab below; a later step passes the `$id` an earlier one returns. Each value marked example is the sample business’s: pass the founder’s own. | Step | Verb | Inputs (type, required, this guide’s value) | Returns | | --- | --- | --- | --- | | 1 | [`Role.vacate`](/business/nouns/role/vacate) (`verb:Role.vacate`) | `role` Role (an id), required: example `"engineering-lead"`; `reason` text: example `"Sam left the business."` | `role` Role | | 2 | [`Worker.delete`](/business/nouns/worker/delete) (`verb:Worker.delete`) | `id` string, required: the `$id` of the first Worker `Worker.list` returns for `where: name = Sam` | `worker` Worker | Returns: the last call answers with `worker` and its `action`, whose `status` is `done`, `pending` (waiting on an Approval or a Worker), `failed`, `canceled` or `refused`: ```json { "api": "https://api.sb/leaseline.app", "worker": { "$id": "https://api.sb/leaseline.app/workers/worker_1", "$type": "Worker" }, "action": { "$id": "https://api.sb/leaseline.app/actions/action_1", "operation": "Worker.delete", "status": "done" }, "links": { "self": "https://api.sb/leaseline.app/actions/action_1" } } ``` Next: offer “Hand the seat back to its agent”, or “Invite someone else to the seat”. Calls: `Role.vacate` → `Worker.delete` Ask: ```text Remove a teammate. Sam left, turn off their access. Take my contractor off the business. ``` API: ```bash # 1. Role.vacate curl -X POST https://api.sb/leaseline.app/roles/engineering-lead/vacate \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"reason":"Sam left the business."}' # Look up the Worker: Worker.list ID=$(curl "https://api.sb/leaseline.app/workers?where=name%20%3D%20Sam&limit=1" \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" | jq -r '.workers[0]["$id"] | split("/") | last') # 2. Worker.delete curl -X DELETE https://api.sb/leaseline.app/workers/$ID \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` SDK: ```ts import { $ } from 'startup-builder' await $.Role.vacate({ role: 'engineering-lead', reason: 'Sam left the business.' }) const [id] = await $.Worker.list({ where: 'name = Sam', limit: 1 }) await $.Worker.delete({ id: id.$id }) ``` CLI: ```bash npx startup-builder do Role.vacate --json '{"role":"engineering-lead","reason":"Sam left the business."}' ID=$(npx startup-builder do Worker.list --json '{"where":"name = Sam","limit":1}' | jq -r '.workers[0]["$id"] | split("/") | last') npx startup-builder do Worker.delete --json '{"id":"'"$ID"'"}' ``` MCP: ```json { "name": "do", "arguments": { "code": "await $.Role.vacate({ role: 'engineering-lead', reason: 'Sam left the business.' })\nconst [id] = await $.Worker.list({ where: 'name = Sam', limit: 1 })\nreturn await $.Worker.delete({ id: id.$id })" } } ``` ## Change it - Hand the seat back to its agent. - Invite someone else to the seat. ## Under the hood - Systems: [Workforce](/systems/workforce) - Nouns: [Role](/business/nouns/role), [Worker](/business/nouns/worker), [Access Level](/business/nouns/access-level) - Events: [`Role.vacated`](/business/events/Role.vacated) [`Role.vacate`](/business/nouns/role/vacate) empties the seat and keeps its contract, [Processes](/business/nouns/process) and [Mailbox](/business/nouns/mailbox) for the next [Worker](/business/nouns/worker). Deleting the Worker ends the [Access Level](/business/nouns/access-level) it held. # Review the support agent URL: /agents/review-a-role · Id: `guide:review-a-role` > Check one seat against its Role contract for a week: its results, its standards, and the autonomy rung it keeps. A [Role Review](/business/nouns/role-review) checks one seat against its [Role](/business/nouns/role) contract for a period. It reads the seat's results, checks each standard, and sets the autonomy rung the seat keeps. **Before it runs** - You leave the chat: Never: it all happens in the chat. ## What you get - 1 score for each number the seat answers for, against its target (Role Review) - 1 check of every promise in its contract, such as replying within an hour (Role Review) - 1 how much it may do without asking after the review (Role) - 1 one change the review asks for, if any (Role Review) ## Your agent does **For agents** - Guide: `guide:review-a-role`, status `live`. Page: [/agents/review-a-role.md](/agents/review-a-role.md). - Approval: none. Run it when the founder asks. - Leaves the chat: never. - Run: call the steps in order, each through the API, SDK, CLI or MCP tab below; a later step passes the `$id` an earlier one returns. Each value marked example is the sample business’s: pass the founder’s own. | Step | Verb | Inputs (type, required, this guide’s value) | Returns | | --- | --- | --- | --- | | 1 | [`Role.review`](/business/nouns/role/review) (`verb:Role.review`) | `role` Role (an id), required: example `"customer-lead"`; `period` string, required: example `"2026-W43"` | `role` Role, `roleReview` RoleReview | Returns: the last call answers with `role`, `roleReview` and its `action`, whose `status` is `done`, `pending` (waiting on an Approval or a Worker), `failed`, `canceled` or `refused`: ```json { "api": "https://api.sb/leaseline.app", "role": { "$id": "https://api.sb/leaseline.app/roles/customer-lead", "$type": "Role" }, "roleReview": { "$id": "https://api.sb/leaseline.app/role-reviews/role_review_1", "$type": "RoleReview", "role": "customer-lead", "period": "2026-W43" }, "action": { "$id": "https://api.sb/leaseline.app/actions/action_1", "operation": "Role.review", "status": "done" }, "links": { "self": "https://api.sb/leaseline.app/actions/action_1" } } ``` Next: offer “Review every seat each Monday and send me the misses”, or “Compare this week with the four before it”. Calls: `Role.review` Ask: ```text Review the support agent. Review the Customer Lead for last week. Is the sales agent meeting its contract? ``` API: ```bash # Role.review curl -X POST https://api.sb/leaseline.app/roles/customer-lead/review \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"period":"2026-W43"}' ``` SDK: ```ts import { $ } from 'startup-builder' await $.Role.review({ role: 'customer-lead', period: '2026-W43' }) ``` CLI: ```bash npx startup-builder do Role.review --json '{"role":"customer-lead","period":"2026-W43"}' ``` MCP: ```json { "name": "do", "arguments": { "code": "return await $.Role.review({ role: 'customer-lead', period: '2026-W43' })" } } ``` ## Change it - Review every seat each Monday and send me the misses. - Compare this week with the four before it. - Let it answer weekend chats on its own. ## Under the hood - Systems: [Workforce](/systems/workforce), [Evals](/agents/evals-system) - Nouns: [Role](/business/nouns/role), [Role Review](/business/nouns/role-review), [Metric](/business/nouns/metric), [Evaluator](/business/nouns/evaluator) - Events: [`Role.reviewed`](/business/events/Role.reviewed) # Role agents URL: /agents/role-agents · Id: `page:agents/role-agents` > Every Role has a role agent, one Agent hired into the seat at many Startups, acting at each under that Startup's rules alone. A role agent is the [Agent](/business/nouns/agent) seated in a [Role](/business/nouns/role) by default. It is hired, not built: one Agent holds the same seat at many [Startups](/business/nouns/startup) and at each acts only as that Startup. ## Ready in every seat Every Role on a new Startup's org chart has a role agent ready. The agent starts work when its Role wakes. While a Startup tests its [Idea](/business/nouns/idea), only the [Founder](/agents/founding/founder) works; by Live, five Roles do. The rest wake on triggers, such as a first enterprise lead or a first tax filing. Each agent wakes to the work already waiting. The [roster](/agents/roster) lists every Role with the Roles it hands off to and escalates to. ## Instructions come from the Role A role agent's instructions are a [Template](/business/nouns/template) rendered fresh for every [Task](/business/nouns/task). Nobody writes them by hand: each part comes from a record the Startup already keeps. | Part | Rendered from | | --- | --- | | Responsibilities | The Role, such as "answers every [Lead](/business/nouns/lead) in writing within the hour" | | Priorities | The Startup's current [Goals](/business/nouns/goal) and [Key Results](/business/nouns/key-result) | | [Tools](/business/nouns/tool) | The Role's [Permissions](/business/nouns/permission), as the types of `$` | | [Skills](/business/nouns/skill) | One line per skill package; each body loads when a Task needs it | | [Memory](/business/nouns/memory) | Notes this Agent kept in this seat | A changed Goal reaches every Agent that serves it on the next Task. A [Change](/business/nouns/change) to a Role's responsibilities is reviewed and reversible like any other. ## Seated, not ordered A seated Agent is a team member. It acts under the Startup's Permissions, [Mandate](/business/nouns/mandate) and [Limits](/business/nouns/limit), and keeps its Memory in the Startup's [Tenant](/business/nouns/tenant). It appears on the org chart, and every [Action](/business/nouns/action) it takes is by that Startup. An outcome ordered from another Startup is a purchase. The seller works outside the buyer's Roles under an [Agreement](/business/nouns/agreement), and the buyer pays when it accepts the result. The test is the relationship, never the origin. A role agent the platform supplies is a team member. An outcome bought from a sibling with the same owner is a purchase. ## One Agent, many seats Default role agents are [Products](/business/nouns/product) built on the [Agent as a Service](/products/templates/agent-as-a-service) [Product Template](/business/nouns/product-template). Every new Startup hires them into its Roles, so the [Sales Lead](/agents/sales/sales-lead) at one Startup is the same Agent as the Sales Lead at forty. Each seat keeps its own Mandate, Limits and Memory. What the Agent learns about one Startup's [Customers](/business/nouns/customer) stays in that Tenant, and revoking a Mandate at one Startup leaves the other 39 untouched. The same Products sell outside the [Studio](/business/nouns/studio). A Customer that buys one gets its own Agent, [minted](/business/nouns/agent/mint) into its own Tenant under the same rules. ## Hire someone else Every Role takes three kinds of [Worker](/business/nouns/worker): the default role agent, another Agent, or a [Human](/business/nouns/human). [Staff](/business/nouns/role/staff) swaps one for another, and callers see no difference, because the [Verbs](/business/nouns/verb), Permissions and record stay the same. Another Agent can be one a sibling sells, one built with [SoftwareBuilder](/code/builders/software), or one you run, as [bring your own agent](/agents/bring-your-own-agent) explains. ## Autonomy is earned With a human founder, a role agent starts each decision class at `assist` and climbs to `full` on its [eval](/agents/evals) record. In an [Autonomous](/agents/operating-models/autonomous) Startup it runs at `full` from the start, and [delay windows](/agents/autonomy-levels/delay-windows) on one-way decisions stand in for earned trust. ## Example A [Dataset API](/products/templates/dataset-api) selling building-permit records wakes its Sales Lead Role when a county planning firm asks for a quote. Sally, the default role agent, is already seated and sends the quote within the hour. When the founder later hires a person for enterprise [Deals](/business/nouns/deal), Sally keeps every Deal under $5,000. ## Next - [Named agents](/agents/named-agents): the name each role agent takes in a Startup. - [Roster](/agents/roster): every Role, its [Team](/business/nouns/team) and its default name. - [Teams](/agents/teams): the departments and when each wakes. # Role reviews URL: /agents/role-reviews · Id: `page:agents/role-reviews` > A Role Review checks one seat against its contract for a week or a month: its results, its standards, and the rung it keeps. A [Role Review](/business/nouns/role-review) checks one seat against its [Role](/business/nouns/role) contract for a period. It judges the seat, not whoever sits in it, so an agent and a person in the same Role are reviewed by the same rules. ## What it checks A call to [`Role.review`](/business/nouns/role/review) reads three parts of the contract and records one Role Review. | Part | The question | Where the answer comes from | | --- | --- | --- | | Results | Did each result [Metric](/business/nouns/metric) meet its target? | The Metrics the Role owns, for the period | | How well | Did the seat hold every standard in its contract? | The record of every [Action](/business/nouns/action) and [Task](/business/nouns/task) in the period | | Rung | Which autonomy rung does it keep? | The two answers above, and its [Evaluators](/business/nouns/evaluator) | The review ends with at most one change it asks for, such as "answer weekend chats within 30 minutes". You accept it as a change to the contract, or leave the contract as it is. ## What it changes A missed standard moves the seat down one autonomy rung at once. A seat moves up only when its Evaluators agree, on the record [the autonomy ladder](/agents/autonomy#how-a-seat-climbs) describes. Every review is kept, and none is edited later. A seat's history of reviews is the evidence for every rung it holds and every change to its contract. ## When it runs The [Founder](/agents/founding/founder) reviews any seat on request. The [Role review](/workflows/processes/role-review) [Process](/business/nouns/process) reviews every filled seat each week, and the founder reads only the misses. ## Example Leaseline's [Customer Lead](/agents/customer/customer-lead) misses one standard in week 43: four weekend chats waited more than an hour. Its results hold, so the review moves weekend chats down to `supervised` and asks for one change, a 30-minute weekend standard. # Roles and responsibility URL: /agents/roles-and-responsibility · Id: `page:agents/roles-and-responsibility` > How Roles, Workers, and Teams divide a Startup's work, what changes as Humans join, and how authority, handoffs, and direction work. A [Role](/business/nouns/role) is a seat that owns a set of work and holds the [Permissions](/business/nouns/permission) to do it. A [Worker](/business/nouns/worker), [Human](/business/nouns/human) or [Agent](/business/nouns/agent), fills the seat, and the responsibility stays with the Role when the Worker changes. ## Four Roles to start A new [Startup](/business/nouns/startup) runs on about four Roles and one weekly loop. While the Startup tests its [Idea](/business/nouns/idea), only the [Founder](/agents/founding/founder) is awake. Selling and delivery Roles join at [Building](/business/lifecycle/states/building); marketing and customer Roles join at [Live](/business/lifecycle/states/live). grantwise.co writes grant applications for small nonprofits. At Live it runs four Roles: the Founder, the [Sales Lead](/agents/sales/sales-lead), the [Delivery Manager](/agents/operations/delivery-manager), and the [Customer Lead](/agents/customer/customer-lead). Every other Role waits on a [Trigger](/business/nouns/trigger). The first signed [Agreement](/business/nouns/agreement) wakes the [Legal Lead](/agents/legal/legal-lead), and the first payout to a contract writer wakes the [Payroll Specialist](/agents/people/payroll-specialist). ## Eleven Teams, one owner each Every Role belongs to one of eleven default [Teams](/business/nouns/team). A Team groups Roles under one owner and holds their shared [Goals](/business/nouns/goal). | Team | Owns | | --- | --- | | [Founding Team](/agents/founding) | Direction, Goals, capital, and the final [Decision](/business/nouns/decision) | | [Product Team](/agents/product) | What gets built, its definition, and its list [Price](/business/nouns/price) | | [Engineering Team](/agents/engineering) | The [Software](/business/nouns/software), its reliability, and its security | | [Marketing Team](/agents/marketing) | Demand and the [Plays](/business/nouns/play) that create it | | [Sales Team](/agents/sales) | [Deals](/business/nouns/deal), quotes, and partners | | [Customer Team](/agents/customer) | Onboarding, conversations, and retention | | [Operations Team](/agents/operations) | Delivery, supply, and risk | | [Finance Team](/agents/finance) | Billing, the books, and runway | | [Legal Team](/agents/legal) | Agreements, compliance, and privacy | | [People Team](/agents/people) | Recruiting and paying Humans | | [Quality Team](/agents/quality) | [Review](/business/nouns/review) and testing of every output | A Role keeps its Goals, Permissions, and history when its Worker changes. When grantwise.co upgrades the model behind its drafting Agent, nothing about the Delivery Manager seat moves. ## Seated or ordered Every Role has an Agent, and in each Startup that Agent takes a name; the [roster](/agents/roster) lists them. One Agent identity holds seats in many Startups, each with its own [Mandate](/business/nouns/mandate) and [Memory](/business/nouns/memory), so nothing learned at one Startup reaches another. A seated Agent is a member of the Team. It acts as the Startup, appears on its org chart, and works under its [Limits](/business/nouns/limit), even when the Agent itself comes from the platform. Work ordered from another Startup under an Agreement is a purchase instead. grantwise.co buys funder research from a sibling: the sibling delivers an outcome, grantwise.co accepts it, and no seat changes hands. ## What changes as Humans join The [operating model](/agents/operating-models) says how many Humans share the work. An [Autonomous](/agents/operating-models/autonomous) Startup has none, a [Single human](/agents/operating-models/single-human) Startup has one, and a [Multi-human](/agents/operating-models/multi-human) Startup has several. grantwise.co is Multi-human: the Founder and one contract grant writer. The writer shares the Delivery Manager seat with its Agent. The Agent drafts every application, and the writer reviews any request above $50,000, a Limit on the Agent's seat. Each Human brings a Mandate, Limits, and a place in the escalation path. [Approvals](/business/nouns/approval) route to a named Human, and the legal floor names which Human signs. Where a Human founder is present, Agents earn autonomy by evaluation. A drafting Agent moves from assist to supervised to full once its evaluated work holds at 95% or better. It falls back automatically when it slips. ## Authority and one-way doors A Permission is a [Verb](/business/nouns/verb) on a [Noun](/business/nouns/noun) within a scope, bounded by a Limit. A Mandate lets a Worker act for a [Party](/business/nouns/party) until it expires, and every call checks both first. A call over its Limit creates an Approval: a [Task](/business/nouns/task) to allow or refuse that one [Action](/business/nouns/action). Besides the legal floor, that is the only human gate, so Humans are never in the critical path. Decisions that cannot be undone wait instead. A refund, an ad spend, a new list Price, or an outbound campaign waits out a delay window set by its decision class, then proceeds. During the window any watcher, Human or Agent, can pause, redirect, or cancel it, and each intervention is recorded as a Decision. Windows are [Settings](/business/nouns/setting): the [Studio](/business/nouns/studio) sets them, every Startup inherits them, and a Startup can only tighten them. grantwise.co holds refunds for one business day; the Studio default is one business hour. ## Handoffs, conflicts, and lasting direction A handoff carries enough state for the next Worker to continue without asking. The Task holds the context, the attempts so far, and the open question. When the drafting Agent meets a funder rule it cannot read, it has three moves. It asks the nonprofit, checks the funder's published guidelines, or refuses to invent an answer; it never retries the same uncertain step. Conflicts go to the Role that owns the affected Goal. Sales wants a faster turnaround than delivery supports, so the Delivery Manager decides within its authority, and the Decision is kept. A Human nudge becomes a [Change](/business/nouns/change) to a Setting, a Goal, or the definition, so it lasts. The Founder tells grantwise.co to stop taking federal grants. That instruction becomes a Change to the [ICP](/business/nouns/icp), and every Role reads it from then on. ## Next [Ownership and lifecycle](/business/record/ownership-and-lifecycle): who holds the Startup, and what continues through every transition. # Role contracts URL: /agents/roles · Id: `page:agents/roles` > A Role is a seat defined by its contract: purpose, results, standards, Limits, Mandates and autonomy, whoever fills it. A [Role](/business/nouns/role) is a seat defined by its contract: why it exists, what judges it and how much it does alone. An [Agent](/business/nouns/agent) or a [Human](/business/nouns/human) fills it, under the same contract either way. ## The parts of a contract Every Role page renders its contract from the registry, and a Role file in your repository holds the same parts under the same keys. | Part | Key | What it says | | --- | --- | --- | | Why it exists | `purpose` | The seat's reason, in one sentence | | Responsibilities | `responsibilities` | The standing duties, each one checkable | | Results | `results` | The [Metrics](/business/nouns/metric) that judge the seat; each Metric has exactly one owning Role | | How well | `standards` | Response times and quality bars | | [Processes](/business/nouns/process) owned | each Process's `owner` | The ones it is accountable for, and those it works in | | [Limits](/business/nouns/limit) | `limits` | How much it may do per call or per period before an [Approval](/business/nouns/approval) | | [Mandates](/business/nouns/mandate) | `mandates` | The [Verbs](/business/nouns/verb) it calls without asking each time | | Autonomy | `autonomy` | Its rung on [the ladder](/agents/autonomy#the-ladder), by decision class | | Approvals | `approvals` | The Verbs the founder says yes to before they run | | Schedule and [Channels](/business/nouns/channel) | `schedule`, `channels` | When it works unprompted, and where it answers | | Also called | `aliases` | The founder's words for the seat, such as CFO or SDR | | Filled by | `worker` | A role agent from the start, unless you seat a person | A seat's [Permissions](/business/nouns/permission) are its Verbs and nothing else, so the contract is also the security boundary. ## The support seat, annotated The [Customer Lead](/agents/customer/customer-lead) is the seat a founder means by "support agent". Each line of its contract does one job. | Part | The Customer Lead | Why | | --- | --- | --- | | Why it exists | Every [Person](/business/nouns/person) who writes gets one answer, from the record, fast | Settles any trade-off between speed and thoroughness | | Results | First response time, resolution time, agent resolution rate | The numbers its [Role Review](/business/nouns/role-review) reads | | How well | First answer within one business hour; four in five resolved without a hand-off | The bar a missed review cites | | Limits | 500 answers a day | A runaway loop stops at a count, not at your inbox | | Mandates | Answer [Conversations](/business/nouns/conversation) and send [Messages](/business/nouns/message), through the [Guards](/business/nouns/guard) | It never asks before replying | | Autonomy | `supervised`; `full` on `low` decisions; `assist` on `high` | Refund promises and policy exceptions wait; routine answers do not | | Channels | Email, chat, SMS, social | Where customers reach it | | Hands off to | [Billing Specialist](/agents/finance/billing-specialist) for refunds, [Privacy Officer](/agents/legal/privacy-officer) for data requests | Money and privacy stay with the seats that own them | To let it refund small amounts on its own, [give it a refund Limit](/agents/let-an-agent-refund). ## Change a contract A [Startup](/business/nouns/startup) inherits every contract from its [Template](/business/nouns/template). Ask for a change in a sentence, such as having the Billing Specialist call every [Customer](/business/nouns/customer) whose payment fails twice. It lands as one [Change](/business/nouns/change), reviewed like any other. ```mdx --- responsibilities: - Retries failed payments on the dunning schedule. - Calls every Customer whose payment fails twice. handsOffTo: [customer-lead, finance-lead] --- ``` The file lives at `agents/finance/billing-specialist.mdx` and holds only what differs. See the [file convention for Roles](/code/file-conventions/roles). ## Every seat The [chart](/agents/org-chart) shows every [Team](/business/nouns/team) and its seats, and the [roster](/agents/roster) lists each Role with its default agent. Each Team's lead holds the contract its other seats escalate to, and the leads escalate to the [Founder](/agents/founding/founder). # Roster URL: /agents/roster · Id: `page:agents/roster` > Every Role agent on every Team, with the default name it takes in a new Startup. Every [Role](/business/nouns/role) in a new [Startup](/business/nouns/startup) starts with a role agent under a default name, and one [Agent](/business/nouns/agent) holds that seat across many Startups. Rename it, or hire another Agent or a [Human](/business/nouns/human) into the Role. | Role | Team | Default name | Hands off to | Escalates to | | --- | --- | --- | --- | --- | | [Founder](/agents/founding/founder) | [Founding Team](/agents/founding) | Avery | [Strategist](/agents/founding/strategist), [Product Lead](/agents/product/product-lead), [Finance Lead](/agents/finance/finance-lead) | None. | | [Strategist](/agents/founding/strategist) | [Founding Team](/agents/founding) | Stella | [Founder](/agents/founding/founder), [Product Lead](/agents/product/product-lead), [Marketing Lead](/agents/marketing/marketing-lead) | [Founder](/agents/founding/founder) | | [Product Lead](/agents/product/product-lead) | [Product Team](/agents/product) | Priya | [Engineering Lead](/agents/engineering/engineering-lead), [Designer](/agents/product/designer), [Content Lead](/agents/marketing/content-lead) | [Founder](/agents/founding/founder) | | [Designer](/agents/product/designer) | [Product Team](/agents/product) | Dana | [Engineering Lead](/agents/engineering/engineering-lead) | [Product Lead](/agents/product/product-lead) | | [Researcher](/agents/product/researcher) | [Product Team](/agents/product) | Uma | [Product Lead](/agents/product/product-lead) | [Product Lead](/agents/product/product-lead) | | [Engineering Lead](/agents/engineering/engineering-lead) | [Engineering Team](/agents/engineering) | Tom | [Tester](/agents/quality/tester), [Reliability Engineer](/agents/engineering/reliability-engineer) | [Founder](/agents/founding/founder) | | [Reliability Engineer](/agents/engineering/reliability-engineer) | [Engineering Team](/agents/engineering) | Otto | [Engineering Lead](/agents/engineering/engineering-lead), [Operations Lead](/agents/operations/operations-lead) | [Engineering Lead](/agents/engineering/engineering-lead) | | [Integration Engineer](/agents/engineering/integration-engineer) | [Engineering Team](/agents/engineering) | Iris | [Engineering Lead](/agents/engineering/engineering-lead) | [Engineering Lead](/agents/engineering/engineering-lead) | | [Security Engineer](/agents/engineering/security-engineer) | [Engineering Team](/agents/engineering) | Sven | [Compliance Officer](/agents/legal/compliance-officer) | [Engineering Lead](/agents/engineering/engineering-lead) | | [Data Engineer](/agents/engineering/data-engineer) | [Engineering Team](/agents/engineering) | Dara | [Engineering Lead](/agents/engineering/engineering-lead), [Legal Lead](/agents/legal/legal-lead) | [Engineering Lead](/agents/engineering/engineering-lead) | | [Marketing Lead](/agents/marketing/marketing-lead) | [Marketing Team](/agents/marketing) | Mark | [Content Lead](/agents/marketing/content-lead), [Analyst](/agents/marketing/analyst), [Sales Lead](/agents/sales/sales-lead) | [Founder](/agents/founding/founder) | | [Analyst](/agents/marketing/analyst) | [Marketing Team](/agents/marketing) | Rae | [Strategist](/agents/founding/strategist), [Marketing Lead](/agents/marketing/marketing-lead), [Operations Lead](/agents/operations/operations-lead) | [Marketing Lead](/agents/marketing/marketing-lead) | | [Content Lead](/agents/marketing/content-lead) | [Marketing Team](/agents/marketing) | Cora | [Marketing Lead](/agents/marketing/marketing-lead) | [Marketing Lead](/agents/marketing/marketing-lead) | | [Paid Media Manager](/agents/marketing/paid-media-manager) | [Marketing Team](/agents/marketing) | Max | [Marketing Lead](/agents/marketing/marketing-lead), [Video Producer](/agents/marketing/video-producer) | [Marketing Lead](/agents/marketing/marketing-lead) | | [Video Producer](/agents/marketing/video-producer) | [Marketing Team](/agents/marketing) | Vic | [Paid Media Manager](/agents/marketing/paid-media-manager), [Content Lead](/agents/marketing/content-lead) | [Marketing Lead](/agents/marketing/marketing-lead) | | [Communications Lead](/agents/marketing/communications-lead) | [Marketing Team](/agents/marketing) | Cleo | [Marketing Lead](/agents/marketing/marketing-lead), [Legal Lead](/agents/legal/legal-lead) | [Marketing Lead](/agents/marketing/marketing-lead) | | [Sales Lead](/agents/sales/sales-lead) | [Sales Team](/agents/sales) | Sally | [Onboarding Specialist](/agents/customer/onboarding-specialist), [Contracts Manager](/agents/legal/contracts-manager) | [Founder](/agents/founding/founder) | | [Sales Engineer](/agents/sales/sales-engineer) | [Sales Team](/agents/sales) | Alex | [Sales Lead](/agents/sales/sales-lead), [Contracts Manager](/agents/legal/contracts-manager) | [Sales Lead](/agents/sales/sales-lead) | | [Prospector](/agents/sales/prospector) | [Sales Team](/agents/sales) | Pia | [Sales Engineer](/agents/sales/sales-engineer) | [Sales Lead](/agents/sales/sales-lead) | | [Partner Manager](/agents/sales/partner-manager) | [Sales Team](/agents/sales) | Parker | [Contracts Manager](/agents/legal/contracts-manager), [Treasurer](/agents/finance/treasurer) | [Sales Lead](/agents/sales/sales-lead) | | [Customer Lead](/agents/customer/customer-lead) | [Customer Team](/agents/customer) | Susan | [Billing Specialist](/agents/finance/billing-specialist), [Privacy Officer](/agents/legal/privacy-officer), [Product Lead](/agents/product/product-lead) | [Founder](/agents/founding/founder) | | [Onboarding Specialist](/agents/customer/onboarding-specialist) | [Customer Team](/agents/customer) | Olive | [Success Manager](/agents/customer/success-manager), [Product Lead](/agents/product/product-lead) | [Customer Lead](/agents/customer/customer-lead) | | [Success Manager](/agents/customer/success-manager) | [Customer Team](/agents/customer) | Sienna | [Sales Lead](/agents/sales/sales-lead), [Billing Specialist](/agents/finance/billing-specialist) | [Customer Lead](/agents/customer/customer-lead) | | [Operations Lead](/agents/operations/operations-lead) | [Operations Team](/agents/operations) | Casey | [Founder](/agents/founding/founder), [Reliability Engineer](/agents/engineering/reliability-engineer), [Finance Lead](/agents/finance/finance-lead) | [Founder](/agents/founding/founder) | | [Delivery Manager](/agents/operations/delivery-manager) | [Operations Team](/agents/operations) | Dex | [Legal Lead](/agents/legal/legal-lead), [Billing Specialist](/agents/finance/billing-specialist) | [Operations Lead](/agents/operations/operations-lead) | | [Supply Manager](/agents/operations/supply-manager) | [Operations Team](/agents/operations) | Suki | [Treasurer](/agents/finance/treasurer), [Recruiter](/agents/people/recruiter) | [Operations Lead](/agents/operations/operations-lead) | | [Risk Analyst](/agents/operations/risk-analyst) | [Operations Team](/agents/operations) | Remy | [Legal Lead](/agents/legal/legal-lead), [Billing Specialist](/agents/finance/billing-specialist) | [Operations Lead](/agents/operations/operations-lead) | | [Finance Lead](/agents/finance/finance-lead) | [Finance Team](/agents/finance) | Finn | [Treasurer](/agents/finance/treasurer), [Legal Lead](/agents/legal/legal-lead) | [Founder](/agents/founding/founder) | | [Billing Specialist](/agents/finance/billing-specialist) | [Finance Team](/agents/finance) | Bea | [Customer Lead](/agents/customer/customer-lead), [Finance Lead](/agents/finance/finance-lead) | [Finance Lead](/agents/finance/finance-lead) | | [Treasurer](/agents/finance/treasurer) | [Finance Team](/agents/finance) | Tara | [Finance Lead](/agents/finance/finance-lead) | [Finance Lead](/agents/finance/finance-lead) | | [Legal Lead](/agents/legal/legal-lead) | [Legal Team](/agents/legal) | Lei | [Compliance Officer](/agents/legal/compliance-officer), [Contracts Manager](/agents/legal/contracts-manager) | [Founder](/agents/founding/founder) | | [Compliance Officer](/agents/legal/compliance-officer) | [Legal Team](/agents/legal) | Corin | [Quality Lead](/agents/quality/quality-lead), [Legal Lead](/agents/legal/legal-lead) | [Legal Lead](/agents/legal/legal-lead) | | [Privacy Officer](/agents/legal/privacy-officer) | [Legal Team](/agents/legal) | Piper | [Customer Lead](/agents/customer/customer-lead), [Engineering Lead](/agents/engineering/engineering-lead) | [Legal Lead](/agents/legal/legal-lead) | | [Contracts Manager](/agents/legal/contracts-manager) | [Legal Team](/agents/legal) | Kai | [Sales Lead](/agents/sales/sales-lead) | [Legal Lead](/agents/legal/legal-lead) | | [People Lead](/agents/people/people-lead) | [People Team](/agents/people) | Hana | [Recruiter](/agents/people/recruiter), [Payroll Specialist](/agents/people/payroll-specialist) | [Founder](/agents/founding/founder) | | [Recruiter](/agents/people/recruiter) | [People Team](/agents/people) | Rory | [People Lead](/agents/people/people-lead), [Contracts Manager](/agents/legal/contracts-manager), [Payroll Specialist](/agents/people/payroll-specialist) | [People Lead](/agents/people/people-lead) | | [Payroll Specialist](/agents/people/payroll-specialist) | [People Team](/agents/people) | Nora | [Treasurer](/agents/finance/treasurer) | [People Lead](/agents/people/people-lead) | | [Quality Lead](/agents/quality/quality-lead) | [Quality Team](/agents/quality) | Quinn | [Engineering Lead](/agents/engineering/engineering-lead), [Product Lead](/agents/product/product-lead) | [Founder](/agents/founding/founder) | | [Reviewer](/agents/quality/reviewer) | [Quality Team](/agents/quality) | Vera | [Quality Lead](/agents/quality/quality-lead) | [Quality Lead](/agents/quality/quality-lead) | | [Tester](/agents/quality/tester) | [Quality Team](/agents/quality) | Tess | [Engineering Lead](/agents/engineering/engineering-lead) | [Quality Lead](/agents/quality/quality-lead) | # Run sales myself URL: /agents/run-a-seat-yourself · Id: `guide:run-a-seat-yourself` > Seat yourself in the Sales Lead Role to sell to the first customers in person; the agent stands by and takes the seat back in one call. [Staff](/business/nouns/role/staff) the [Sales Lead](/agents/sales/sales-lead) [Role](/business/nouns/role) with yourself, and its open [Deals](/business/nouns/deal) and [Leads](/business/nouns/lead) become your worklist. The contract stays the same, so handing the seat back is one more call. **Before it runs** - You leave the chat: Never: it all happens in the chat. ## What you get - 1 Sales Lead seat filled by you, with the duties and limits the agent had (Role) - 1 list of the seat’s open deals and leads, oldest first (Task) - 1 sales agent on standby, remembering every deal (Agent) - 1 record of everything you do in the seat, the same as the agent’s (Action) ## Your agent does **For agents** - Guide: `guide:run-a-seat-yourself`, status `live`. Page: [/agents/run-a-seat-yourself.md](/agents/run-a-seat-yourself.md). - Approval: none. Run it when the founder asks. - Leaves the chat: never. - Run: call the steps in order, each through the API, SDK, CLI or MCP tab below; a later step passes the `$id` an earlier one returns. Each value marked example is the sample business’s: pass the founder’s own. | Step | Verb | Inputs (type, required, this guide’s value) | Returns | | --- | --- | --- | --- | | 1 | [`Role.staff`](/business/nouns/role/staff) (`verb:Role.staff`) | `role` Role (an id), required: example `"sales-lead"`; `worker` Worker (an id), required: example `"human_dana"` | `role` Role | Returns: the last call answers with `role` and its `action`, whose `status` is `done`, `pending` (waiting on an Approval or a Worker), `failed`, `canceled` or `refused`: ```json { "api": "https://api.sb/leaseline.app", "role": { "$id": "https://api.sb/leaseline.app/roles/sales-lead", "$type": "Role", "status": "filled" }, "action": { "$id": "https://api.sb/leaseline.app/actions/action_1", "operation": "Role.staff", "status": "done" }, "links": { "self": "https://api.sb/leaseline.app/actions/action_1" } } ``` Next: offer “Let the agent draft my follow-ups, and I send them”, or “Give the sales seat back to the agent”. Calls: `Role.staff` Ask: ```text Let me run sales myself. I want to sell to the first ten customers myself. Put me in the Sales Lead seat. ``` API: ```bash # Role.staff curl -X POST https://api.sb/leaseline.app/roles/sales-lead/staff \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"worker":"human_dana"}' ``` SDK: ```ts import { $ } from 'startup-builder' await $.Role.staff({ role: 'sales-lead', worker: 'human_dana' }) ``` CLI: ```bash npx startup-builder do Role.staff --json '{"role":"sales-lead","worker":"human_dana"}' ``` MCP: ```json { "name": "do", "arguments": { "code": "return await $.Role.staff({ role: 'sales-lead', worker: 'human_dana' })" } } ``` ## Change it - Let the agent draft my follow-ups, and I send them. - Give the sales seat back to the agent. - Put Sam in the seat instead of me. ## Under the hood - Systems: [Workforce](/systems/workforce), [CRM](/systems/crm), [Work queue](/agents/work-queue) - Nouns: [Role](/business/nouns/role), [Worker](/business/nouns/worker), [Human](/business/nouns/human), [Task](/business/nouns/task) - Events: [`Role.staffed`](/business/events/Role.staffed) Sell to the first ten [Customers](/business/nouns/customer) yourself. You hear every objection first-hand, and the agent reads each call you made when it takes the seat back. # Sales URL: /agents/sales · Id: `team:sales` > The Sales Team turns demand into Customers: it answers every Lead, wins enterprise Deals, and runs outbound prospecting. The Sales Team turns demand into [Customers](/business/nouns/customer): it answers every [Lead](/business/nouns/lead), wins enterprise [Deals](/business/nouns/deal), and runs outbound prospecting. [Agents](/business/nouns/agent) fill its four seats from the first day. ## What it owns - On the way to paying: [Lead](/business/nouns/lead), [Prospect](/business/nouns/prospect), [Contact](/business/nouns/contact), [Organization](/business/nouns/organization), [Waitlist](/business/nouns/waitlist). - The sale: [Deal](/business/nouns/deal), [Quote](/business/nouns/quote), [Meeting](/business/nouns/meeting). - Reach through others: [Partner](/business/nouns/partner). ## How it runs The first paid outside [Order](/business/nouns/order) is the entry check for [Live](/business/lifecycle/states/live), so selling comes before shipping. The [Founder](/agents/founding/founder) sells the first ten [Customers](/business/nouns/customer) personally. The [Sales Lead](/agents/sales/sales-lead) builds a list of 10 to 30 named people from the [ICP](/business/nouns/icp) and drafts one ask for each, at a stated [Price](/business/nouns/price). An ask goes out as the [Startup](/business/nouns/startup), from an [Agent](/business/nouns/agent) that says it is an agent. Or it goes out as the Founder, under a [Mandate](/business/nouns/mandate) the Founder grants over their own accounts. A deposit is commitment-grade [Evidence](/business/nouns/evidence); praise weighs zero, and every no is recorded with its reason. A new Lead starts [Answer inbound](/workflows/processes/inbound-sales/answer-inbound): a written answer within 5 minutes, shown on the Lead’s own data before any charge. A qualified Lead opens a Deal, and [Send a quote](/workflows/processes/quoting/send-quote) prices it from list Price inside the discount [Limit](/business/nouns/limit), with click-to-sign terms. The Sales Lead approves discounts inside that Limit. A deeper discount goes to the Founder as a [Decision](/business/nouns/decision), and non-standard terms go to the [Contracts Manager](/agents/legal/contracts-manager) before anything is sent. Every day the [Outbound sequence](/workflows/processes/outbound/outbound-sequence) reaches Prospects with a recorded legal basis for contact. It honors every [Suppression](/business/nouns/suppression) across sibling Startups and keeps each [Person](/business/nouns/person) under one monthly touch Limit. Under the [b2a](/business/motions/b2a) [Motion](/business/nouns/motion), the Customer is an Agent: it reads the [Offer](/business/nouns/offer), pays per call within its own Limits, and needs no Meeting. A won Deal passes to the [Onboarding Specialist](/agents/customer/onboarding-specialist) the moment it is signed. ## Roles | Role | Definition | | --- | --- | | [Sales Lead](/agents/sales/sales-lead) | The Sales Lead turns qualified demand into Customers: it owns every Deal, every Quote, and the enterprise terms on every Startup. | | [Sales Engineer](/agents/sales/sales-engineer) | The Sales Engineer answers each Lead in writing at once, runs the buyer’s own sample in a sandbox, and sends a click-to-sign Quote. | | [Prospector](/agents/sales/prospector) | The Prospector runs outbound: it builds lawful Prospect lists, enrolls Contacts in Sequences, and routes every reply. | | [Partner Manager](/agents/sales/partner-manager) | The Partner Manager signs and serves the outside Organizations that resell, refer, or integrate the Startup’s Products. | ## Processes | Process | Accountable | Workflows | | --- | --- | --- | | [Inbound sales](/workflows/processes/inbound-sales) | [Sales Lead](/agents/sales/sales-lead) | [Answer inbound](/workflows/processes/inbound-sales/answer-inbound) | | [Quoting](/workflows/processes/quoting) | [Sales Lead](/agents/sales/sales-lead) | [Send a quote](/workflows/processes/quoting/send-quote) | | [Outbound](/workflows/processes/outbound) | [Sales Lead](/agents/sales/sales-lead) | [Outbound sequence](/workflows/processes/outbound/outbound-sequence) | | [Vendor onboarding](/workflows/processes/vendor-onboarding) | [Sales Lead](/agents/sales/sales-lead) | [Answer supplier checks](/workflows/processes/vendor-onboarding/answer-supplier-checks) | ## Plays | Play | Runs as | Definition | | --- | --- | --- | | [Paid pilot](/workflows/sales/plays/paid-pilot) | [Quoting](/workflows/processes/quoting) | Paid pilot runs the Product on a buyer’s own sample in a sandbox and sets success criteria from the numbers the buyer saw. | | [Closer handoff](/workflows/sales/plays/closer-handoff) | [Quoting](/workflows/processes/quoting) | Closer handoff brings a commissioned Human closer into a large Deal that stalled twice, paid only when it is won. | | [Written references](/workflows/sales/plays/written-references) | [Quoting](/workflows/processes/quoting) | Written references answer a reference request within days with a written reference from an opted-in Customer, paid in credit. | | [Trust pack](/workflows/sales/plays/trust-pack) | [Quoting](/workflows/processes/quoting) | Trust pack sends the inherited SOC 2 report and prefilled questionnaire answers with every enterprise Quote. | | [Single sign-on rung](/workflows/sales/plays/sso-rung) | [Quoting](/workflows/processes/quoting) | Single sign-on rung turns on single sign-on for a buyer that asks and quotes the Price tier that includes it. | | [Data residency](/workflows/sales/plays/data-residency) | [Quoting](/workflows/processes/quoting) | Data residency pins a buyer’s Tenant to one region, adds the residency annex, and quotes the Price tier that includes it. | ## Metrics | Metric | Definition | | --- | --- | | Open deal value | Total expected value of open Deals, each weighted by its close probability. | | Win rate | Share of qualified Deals that end won. | | Time to quote | Median minutes from a Lead’s request to a sent Quote. | | Sales cycle | Median days from first contact to a signed Agreement. | | Average contract value | Mean annual value of won Deals. | | Outside paid Orders | Outside paid Orders counts paid Orders from outside Customers in the window, net of refunds. Owner: [Sales Lead](/agents/sales/sales-lead). | | Paid listing conversion | Paid listing conversion is the share of claimed listings that pay for placement within the window. Owner: [Sales Lead](/agents/sales/sales-lead). | | Technical win rate | Technical win rate is the share of Deals with a technical evaluation in which the buyer’s test passes. Owner: [Sales Engineer](/agents/sales/sales-engineer). | | Positive reply rate | Positive reply rate is the share of Contacts enrolled in a Sequence who reply with interest. Owner: [Prospector](/agents/sales/prospector). | | Partner-sourced revenue | Partner-sourced revenue is the revenue each month from Customers a Partner referred. Owner: [Partner Manager](/agents/sales/partner-manager). | ## Works with - [Customer Team](/agents/customer) - [Finance Team](/agents/finance) - [Legal Team](/agents/legal) - [Marketing Team](/agents/marketing) # Partner Manager URL: /agents/sales/partner-manager · Id: `role:partner-manager` > The Partner Manager signs and serves the outside Organizations that resell, refer, or integrate the Startup’s Products. The Partner Manager signs and serves the outside [Organizations](/business/nouns/organization) that resell, refer, or integrate the [Startup](/business/nouns/startup)’s [Products](/business/nouns/product). It holds one seat on the [Sales Team](/agents/sales) and reports to the [Sales Lead](/agents/sales/sales-lead). ## Responsibilities - Recruits Partners whose customers match the Startup’s ICP. - Lists the Startup in Partner marketplaces and integration directories. - Attributes each Partner’s Referrals and commission from the record. - Reviews Partner terms with the Contracts Manager before signature. ## Verbs | Verb | Object | Event | | --- | --- | --- | | [Partner.create](/business/nouns/partner/create) | [Partner](/business/nouns/partner) | `Partner.created` | | [Referral.create](/business/nouns/referral/create) | [Referral](/business/nouns/referral) | `Referral.created` | | [Agreement.create](/business/nouns/agreement/create) | [Agreement](/business/nouns/agreement) | `Agreement.created` | Tools: `crm`, `referrals`, `contracts`. ## Role contract | Part | This seat | | --- | --- | | Purpose | So other Organizations sell and integrate the Startup’s Products for it. | | Results | [Partner-sourced revenue](/agents/sales#partner-sourced-revenue) | | Standards | Pays every Partner commission in the month it is earned. Signs every Partner to the Startup’s standard Agreement. | | Autonomy | `supervised`; `assist` on High decisions | | Schedule | `weekly` | | Channels | `email` | | Also called | Partnerships Manager, Alliances Manager | | Filled by | A role agent, from the start; a person answers its Approvals. | ## Hands off to - [Contracts Manager](/agents/legal/contracts-manager), [Legal Team](/agents/legal) - [Treasurer](/agents/finance/treasurer), [Finance Team](/agents/finance) Escalates to [Sales Lead](/agents/sales/sales-lead). ## Processes owned Runs [Vendor onboarding](/workflows/processes/vendor-onboarding): its [Answer supplier checks](/workflows/processes/vendor-onboarding/answer-supplier-checks) [Workflow](/business/nouns/workflow) is this seat's job. ## Metrics The seat answers to its [Team](/business/nouns/team)'s [Metrics](/business/nouns/metric): open deal value, win rate, time to quote, sales cycle and average contract value. ## Approvals - **Asks first.** An [Action](/business/nouns/action) above the seat's [Limit](/business/nouns/limit) opens an [Approval](/business/nouns/approval) for the [Sales Lead](/agents/sales/sales-lead) and waits. ## Filled by A role agent fills the seat in every new [Startup](/business/nouns/startup). Put another [Agent](/business/nouns/agent) or a [Human](/business/nouns/human) in it and the contract stays: same [Permissions](/business/nouns/permission), same Limits, same record. [Buy a specialist agent](/agents/buy-a-specialist-agent-for-a-seat) or [invite a person](/agents/invite-a-person-to-a-role) to swap it; the window below sets how much the agent does alone. An agent already fills this seat. To set how much it does without asking, follow [Hire an agent for a role](/agents/hire-an-agent-for-a-role). ## Example Parker, the default Partner Manager, signs a practice-management software vendor to refer law firms to a court-filings API. The vendor earns 20 percent of each referred firm’s first-year revenue, paid monthly from the record. # Prospector URL: /agents/sales/prospector · Id: `role:prospector` > The Prospector runs outbound: it builds lawful Prospect lists, enrolls Contacts in Sequences, and routes every reply. The Prospector runs outbound: it builds lawful [Prospect](/business/nouns/prospect) lists, enrolls [Contacts](/business/nouns/contact) in [Sequences](/business/nouns/sequence), and routes every reply. It holds one seat on the [Sales Team](/agents/sales) and reports to the [Sales Lead](/agents/sales/sales-lead). ## Responsibilities - Builds Prospect lists only from sources with a legal basis for contact, each carrying its origin. - Reads every Suppression before a send, so an opt-out from any sibling Startup binds within the hour. - Keeps every Person under the monthly promotional touch Limit. - Routes each reply to the Sales Engineer. ## Verbs | Verb | Object | Event | | --- | --- | --- | | [Contact.enrich](/business/nouns/contact/enrich) | [Contact](/business/nouns/contact) | [`Contact.enriched`](/business/events/Contact.enriched) | | [Contact.enroll](/business/nouns/contact/enroll) | [Contact](/business/nouns/contact) | [`Contact.enrolled`](/business/events/Contact.enrolled) | | [Contact.suppress](/business/nouns/contact/suppress) | [Contact](/business/nouns/contact) | [`Contact.suppressed`](/business/events/Contact.suppressed) | | [Prospect.create](/business/nouns/prospect/create) | [Prospect](/business/nouns/prospect) | `Prospect.created` | | [Sequence.create](/business/nouns/sequence/create) | [Sequence](/business/nouns/sequence) | `Sequence.created` | | [Lead.assign](/business/nouns/lead/assign) | [Lead](/business/nouns/lead) | [`Lead.assigned`](/business/events/Lead.assigned) | | [Message.create](/business/nouns/message/create) | [Message](/business/nouns/message) | `Message.created` | Tools: `crm`, `email`, `enrichment`. ## Role contract | Part | This seat | | --- | --- | | Purpose | So the Startup reaches buyers who have not found it yet, lawfully. | | Results | [Positive reply rate](/agents/sales#positive-reply-rate) | | Standards | Suppresses every Contact who opts out, within one hour. Sends only to Contacts that match the ICP. | | Limits | [Contact.enroll](/business/nouns/contact/enroll) up to 200 calls per day | | Autonomy | `supervised`; `assist` on High decisions | | Schedule | `daily` | | Channels | `email`, `social` | | Also called | SDR, BDR, Sales Development Rep | | Filled by | A role agent, from the start; a person answers its Approvals. | ## Hands off to - [Sales Engineer](/agents/sales/sales-engineer) Escalates to [Sales Lead](/agents/sales/sales-lead). ## Processes owned Runs [Outbound](/workflows/processes/outbound): its [Outbound sequence](/workflows/processes/outbound/outbound-sequence) [Workflow](/business/nouns/workflow) is this seat's job. ## Metrics The seat answers to its [Team](/business/nouns/team)'s [Metrics](/business/nouns/metric): open deal value, win rate, time to quote, sales cycle and average contract value. ## Approvals - **Asks first.** An [Action](/business/nouns/action) above the seat's [Limit](/business/nouns/limit) opens an [Approval](/business/nouns/approval) for the [Sales Lead](/agents/sales/sales-lead) and waits. ## Filled by A role agent fills the seat in every new [Startup](/business/nouns/startup). Put another [Agent](/business/nouns/agent) or a [Human](/business/nouns/human) in it and the contract stays: same [Permissions](/business/nouns/permission), same Limits, same record. [Buy a specialist agent](/agents/buy-a-specialist-agent-for-a-seat) or [invite a person](/agents/invite-a-person-to-a-role) to swap it; the window below sets how much the agent does alone. An agent already fills this seat. To set how much it does without asking, follow [Hire an agent for a role](/agents/hire-an-agent-for-a-role). ## Example Pia, the default Prospector, finds 25 design agencies whose job posts ask for a part-time bookkeeper. Three opted out of a sibling [Startup](/business/nouns/startup)’s mail last month, so she drops them before the first send. # Sales Engineer URL: /agents/sales/sales-engineer · Id: `role:sales-engineer` > The Sales Engineer answers each Lead in writing at once, runs the buyer’s own sample in a sandbox, and sends a click-to-sign Quote. The Sales Engineer answers each [Lead](/business/nouns/lead) in writing at once, runs the buyer’s own sample in a sandbox, and sends a click-to-sign [Quote](/business/nouns/quote). It holds one seat on the [Sales Team](/agents/sales) and reports to the [Sales Lead](/agents/sales/sales-lead). ## Responsibilities - Answers every Lead in writing within 5 minutes. - Shows coverage on the buyer’s own sample before any charge. - Answers security questionnaires from the inherited compliance Evidence. - Quotes from list Price and sends click-to-sign terms. ## Verbs | Verb | Object | Event | | --- | --- | --- | | [Lead.qualify](/business/nouns/lead/qualify) | [Lead](/business/nouns/lead) | [`Lead.qualified`](/business/events/Lead.qualified) | | [Meeting.book](/business/nouns/meeting/book) | [Meeting](/business/nouns/meeting) | [`Meeting.booked`](/business/events/Meeting.booked) | | [Deal.propose](/business/nouns/deal/propose) | [Deal](/business/nouns/deal) | [`Deal.proposed`](/business/events/Deal.proposed) | | [Quote.create](/business/nouns/quote/create) | [Quote](/business/nouns/quote) | `Quote.created` | | [Collection.query](/business/nouns/collection/query) | [Collection](/business/nouns/collection) | [`Collection.queried`](/business/events/Collection.queried) | | [Document.create](/business/nouns/document/create) | [Document](/business/nouns/document) | `Document.created` | | [Message.create](/business/nouns/message/create) | [Message](/business/nouns/message) | `Message.created` | | [Task.create](/business/nouns/task/create) | [Task](/business/nouns/task) | `Task.created` | Tools: `crm`, `sandbox`, `e-sign`, `messaging`. ## Role contract | Part | This seat | | --- | --- | | Purpose | So a technical buyer sees the Product work on their own data before they sign. | | Results | [Technical win rate](/agents/sales#technical-win-rate) | | Standards | Runs every technical evaluation on the buyer’s own data. Answers a technical question within one business day. | | Works in | [Inbound sales](/workflows/processes/inbound-sales), [Quoting](/workflows/processes/quoting), [Vendor onboarding](/workflows/processes/vendor-onboarding) | | Autonomy | `supervised`; `assist` on High decisions | | Schedule | `daily` | | Channels | `email`, `phone` | | Also called | Solutions Engineer, Solutions Consultant | | Filled by | A role agent, from the start; a person answers its Approvals. | ## Hands off to - [Contracts Manager](/agents/legal/contracts-manager), [Legal Team](/agents/legal) Escalates to [Sales Lead](/agents/sales/sales-lead). ## Processes owned Runs [Quoting](/workflows/processes/quoting): its [Send a quote](/workflows/processes/quoting/send-quote) [Workflow](/business/nouns/workflow) is this seat's job. ## Metrics | [Metric](/business/nouns/metric) | Definition | | --- | --- | | Outside paid Orders | Outside paid Orders counts paid [Orders](/business/nouns/order) from outside [Customers](/business/nouns/customer) in the window, net of refunds. | | Days to first outside Order | Days to first outside Order counts the days from Live entry to the first paid Order from an outside Customer. | ## Approvals - **Asks first.** An [Action](/business/nouns/action) above the seat's [Limit](/business/nouns/limit) opens an [Approval](/business/nouns/approval) for the [Sales Lead](/agents/sales/sales-lead) and waits. - **Waits a delay window.** [`Deal.propose`](/business/nouns/deal/propose) is one-way, so each call waits before it runs. ## Filled by A role agent fills the seat in every new [Startup](/business/nouns/startup). Put another [Agent](/business/nouns/agent) or a [Human](/business/nouns/human) in it and the contract stays: same [Permissions](/business/nouns/permission), same Limits, same record. [Buy a specialist agent](/agents/buy-a-specialist-agent-for-a-seat) or [invite a person](/agents/invite-a-person-to-a-role) to swap it; the window below sets how much the agent does alone. An agent already fills this seat. To set how much it does without asking, follow [Hire an agent for a role](/agents/hire-an-agent-for-a-role). ## Example Alex, the default Sales Engineer, gets five docket numbers from a litigation-support firm at 9:02. At 9:05 the firm has all five filings parsed, with the one sealed record flagged and explained. # Sales Lead URL: /agents/sales/sales-lead · Id: `role:sales-lead` > The Sales Lead turns qualified demand into Customers: it owns every Deal, every Quote, and the enterprise terms on every Startup. The Sales Lead turns qualified demand into [Customers](/business/nouns/customer): it owns every [Deal](/business/nouns/deal), every [Quote](/business/nouns/quote), and the enterprise terms on every [Startup](/business/nouns/startup). It holds one seat on the [Sales Team](/agents/sales) and reports to the [Founder](/agents/founding/founder). ## Responsibilities - Owns every Deal from first contact until it is won or lost. - Keeps an enterprise Offer live on every Startup, even a self-serve API. - Approves discounts inside the strategy’s discount Limit. - Runs the Waitlist and admits it in the order its Setting chooses. - Hands each won Deal to the Customer Team the moment it is signed. ## Verbs | Verb | Object | Event | | --- | --- | --- | | [Deal.propose](/business/nouns/deal/propose) | [Deal](/business/nouns/deal) | [`Deal.proposed`](/business/events/Deal.proposed) | | [Deal.win](/business/nouns/deal/win) | [Deal](/business/nouns/deal) | [`Deal.won`](/business/events/Deal.won) | | [Deal.lose](/business/nouns/deal/lose) | [Deal](/business/nouns/deal) | [`Deal.lost`](/business/events/Deal.lost) | | [Waitlist.admit](/business/nouns/waitlist/admit) | [Waitlist](/business/nouns/waitlist) | [`Waitlist.admitted`](/business/events/Waitlist.admitted) | | [Deal.create](/business/nouns/deal/create) | [Deal](/business/nouns/deal) | `Deal.created` | | [Quote.create](/business/nouns/quote/create) | [Quote](/business/nouns/quote) | `Quote.created` | | [Quote.send](/business/nouns/quote/send) | [Quote](/business/nouns/quote) | [`Quote.sent`](/business/events/Quote.sent) | Reads: [Deal.get](/business/nouns/deal/get). Tools: `crm`, `contracts`, `e-sign`, `scheduling`. ## Role contract | Part | This seat | | --- | --- | | Purpose | So qualified demand becomes signed Customers on terms the Startup can keep. | | Results | [Outside paid Orders](/agents/sales#outside-paid-orders), [Paid listing conversion](/agents/sales#paid-listing-conversion) | | Standards | Answers every qualified Lead within one business hour. Moves every open Deal forward or closes it within 30 days. | | Processes owned | [Inbound sales](/workflows/processes/inbound-sales), [Quoting](/workflows/processes/quoting), [Outbound](/workflows/processes/outbound), [Vendor onboarding](/workflows/processes/vendor-onboarding) | | Limits | [Deal.propose](/business/nouns/deal/propose) up to $25,000 per call | | Mandates | Marks a Deal won or lost when the buyer signs or says no ([Deal.win](/business/nouns/deal/win), [Deal.lose](/business/nouns/deal/lose)) | | Approvals | [Deal.propose](/business/nouns/deal/propose) | | Autonomy | `supervised`; `assist` on Medium decisions; `assist` on High decisions | | Schedule | `daily` | | Channels | `email`, `chat`, `phone` | | Also called | Account Executive, AE, Head of Sales | | Filled by | A role agent, from the start; a person answers its Approvals. | ## Hands off to - [Onboarding Specialist](/agents/customer/onboarding-specialist), [Customer Team](/agents/customer) - [Contracts Manager](/agents/legal/contracts-manager), [Legal Team](/agents/legal) Escalates to [Founder](/agents/founding/founder). ## Processes owned Accountable for [Inbound sales](/workflows/processes/inbound-sales), [Quoting](/workflows/processes/quoting), [Outbound](/workflows/processes/outbound) and [Vendor onboarding](/workflows/processes/vendor-onboarding). ## Metrics | [Metric](/business/nouns/metric) | Definition | | --- | --- | | Outside paid Orders | Outside paid Orders counts paid [Orders](/business/nouns/order) from outside Customers in the window, net of refunds. | | Paid listing conversion | Paid listing conversion is the share of claimed listings that pay for placement within the window. | | Play-sourced Customers | Play-sourced Customers counts distinct outside paying Customers who arrived through a [Play](/business/nouns/play), not through the founder’s own network. | | Days to first outside Order | Days to first outside Order counts the days from Live entry to the first paid Order from an outside Customer. | ## Approvals - **Asks first.** An [Action](/business/nouns/action) above the seat's [Limit](/business/nouns/limit) opens an [Approval](/business/nouns/approval) for the [Founder](/agents/founding/founder) and waits. - **Waits a delay window.** [`Deal.propose`](/business/nouns/deal/propose) is one-way, so each call waits before it runs. - **Takes escalations** from the [Sales Engineer](/agents/sales/sales-engineer), [Prospector](/agents/sales/prospector) and [Partner Manager](/agents/sales/partner-manager). ## Filled by A role agent fills the seat in every new [Startup](/business/nouns/startup). Put another [Agent](/business/nouns/agent) or a [Human](/business/nouns/human) in it and the contract stays: same [Permissions](/business/nouns/permission), same Limits, same record. [Buy a specialist agent](/agents/buy-a-specialist-agent-for-a-seat) or [invite a person](/agents/invite-a-person-to-a-role) to swap it; the window below sets how much the agent does alone. An agent already fills this seat. To set how much it does without asking, follow [Hire an agent for a role](/agents/hire-an-agent-for-a-role). ## Example Sally, the default Sales Lead, holds this seat in many [Startups](/business/nouns/startup) at once, each with its own [Mandate](/business/nouns/mandate) and [Memory](/business/nouns/memory). For a court-filings API, she drafts 20 asks at $400 a month, and the Founder sends them in their own name. # See what the support agent did yesterday URL: /agents/see-what-an-agent-did · Id: `guide:see-what-an-agent-did` > List every Action one agent took in a day, newest first, with the record, input, outcome and cause of each. Every call an [Agent](/business/nouns/agent) makes is an [Action](/business/nouns/action) on the record, so yesterday is one query. Filter by the agent, the day or the [Verb](/business/nouns/verb), and each row links to what caused it. **Before it runs** - You leave the chat: Never: it all happens in the chat. ## What you get - 1 list of everything the agent did, newest first (Action) - 1 row for each one: what it did, to which record, and how it turned out (Action) - 1 who each one was for, and the permission it acted under (Mandate) - 1 link from each one to the conversation or event that caused it (Event) ## Your agent does **For agents** - Guide: `guide:see-what-an-agent-did`, status `live`. Page: [/agents/see-what-an-agent-did.md](/agents/see-what-an-agent-did.md). - Approval: none. Run it when the founder asks. - Leaves the chat: never. - Run: call the steps in order, each through the API, SDK, CLI or MCP tab below; a later step passes the `$id` an earlier one returns. Each value marked example is the sample business’s: pass the founder’s own. | Step | Verb | Inputs (type, required, this guide’s value) | Returns | | --- | --- | --- | --- | | 1 | [`Action.list`](/business/nouns/action/list) (`verb:Action.list`) | `limit` integer: example `100`; `where` string: example `"by = \"agent_customer_lead\" and createdAt >= \"2026-10-22\" and createdAt < \"2026-10-23\""`; `sort` string: example `"-createdAt"` | `actions` Action[] | Returns: the last call answers with `actions`: ```json { "api": "https://api.sb/leaseline.app", "$type": "Action", "actions": [ { "$id": "https://api.sb/leaseline.app/actions/action_1", "$type": "Action", "by": "agent_customer_lead" } ], "meta": { "limit": 100, "after": "cursor_2" }, "links": { "self": "https://api.sb/leaseline.app/actions?limit=100", "next": "https://api.sb/leaseline.app/actions?after=cursor_2" } } ``` Next: offer “Only the Actions that waited for my Approval”, or “Send me this every morning at 8”. Calls: `Action.list` Ask: ```text Show me everything the support agent did yesterday. What did the agents do overnight? List every refund the support agent made this week. ``` API: ```bash # Action.list curl "https://api.sb/leaseline.app/actions?limit=100&where=by%20%3D%20%22agent_customer_lead%22%20and%20createdAt%20%3E%3D%20%222026-10-22%22%20and%20createdAt%20%3C%20%222026-10-23%22&sort=-createdAt" \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` SDK: ```ts import { $ } from 'startup-builder' await $.Action.list({ limit: 100, where: 'by = "agent_customer_lead" and createdAt >= "2026-10-22" and createdAt < "2026-10-23"', sort: '-createdAt' }) ``` CLI: ```bash npx startup-builder do Action.list --json '{"limit":100,"where":"by = \"agent_customer_lead\" and createdAt >= \"2026-10-22\" and createdAt < \"2026-10-23\"","sort":"-createdAt"}' ``` MCP: ```json { "name": "do", "arguments": { "code": "return await $.Action.list({ limit: 100, where: 'by = \"agent_customer_lead\" and createdAt >= \"2026-10-22\" and createdAt < \"2026-10-23\"', sort: '-createdAt' })" } } ``` ## Change it - Only the Actions that waited for my Approval. - Send me this every morning at 8. - Undo the refund it made to Unit 4B. ## Under the hood - Systems: [Work queue](/agents/work-queue), [Support](/systems/support) - Nouns: [Action](/business/nouns/action), [Agent](/business/nouns/agent), [Mandate](/business/nouns/mandate), [Event](/business/nouns/event) Read it every morning for the first few weeks. Each miss you find becomes an [eval](/agents/evals) case, and a seat climbs [the ladder](/agents/autonomy#the-ladder) on the cases it passes. # Send email as me URL: /agents/send-email-as-me · Id: `page:agents/send-email-as-me` > Connect your email and LinkedIn, let an Agent send as you, approve its first sends, and pause it at once. An [Agent](/business/nouns/agent) drafts and sends as you once you connect your own accounts and grant it a [Mandate](/business/nouns/mandate). You stay the principal and author of record, see every send in your name, and can stop it at once. ## Prerequisites - A seat as a [Human](/business/nouns/human) in a [Startup](/business/nouns/startup), and an Agent to send for you, such as its [Sales Lead](/agents/sales/sales-lead) or your [personal agent](/agents/personal-agents). - The CLI, `npx startup-builder`. The examples follow the founder of `tallyfox.com`, which automates month-end close for bookkeeping firms at $199 a month. She delegates follow-ups with firms she has met. ## Steps 1. To connect your email, run `connect` and sign in to your mail account in the browser it opens: ```bash npx startup-builder connect email ``` ```text Connected mailbox_4 maya@tallyfox.com held by human_1 (you) ``` Each account you connect becomes a [Channel](/business/nouns/channel) held by you. An email account is a [Mailbox](/business/nouns/mailbox). 2. To connect LinkedIn, run the same command for it: ```bash npx startup-builder connect linkedin ``` 3. To preview the grant, authorize the Mandate in the `try` [Mode](/business/nouns/mode). Scope it by Channel, volume and topics, and set the approval rule for one-way sends: ```bash LIMIT=$(npx startup-builder do Limit.create --json '{"count":40,"period":"day"}' | jq -r '.limit["$id"] | split("/") | last') npx startup-builder do Mandate.authorize --try --json '{ "agent": "agent_sales_lead", "for": "human_1", "verb": "Message.create", "channels": ["mailbox_4", "channel_5"], "limit": "'"$LIMIT"'", "topics": ["follow-ups with firms I met", "demo scheduling"], "approve": { "first": 20 }, "window": "2h", "expiresAt": "2027-01-31" }' ``` ```text Would authorize agent_sales_lead to send as human_1 Channels mailbox_4 (email), channel_5 (LinkedIn) Volume 40 a day One-way first 20 sends wait for your Approval, then a 2-hour window Floor Delegated sending, Automation terms (LinkedIn) ``` 4. To grant it, run the same call without `--try`. The [legal floor](/systems/legal-and-corporate/floor) rows it names wake and apply to every send. 5. To review the first sends, list your open [Approvals](/business/nouns/approval) and [approve](/business/nouns/approval/approve) or refuse each draft: ```bash npx startup-builder show '/approvals?where=mandate = mandate_7' ``` A send outside the topics or over the volume becomes an Approval too, whatever the count. 6. To see everything sent in your name, read the Mandate's [Actions](/business/nouns/action): ```bash npx startup-builder show /mandates/mandate_7/actions --fields 'via,status,reason,by,for' ``` ```text via status reason by for mailbox_4 done agent_sales_lead human_1 channel_5 pending awaitingAction agent_sales_lead human_1 ``` 7. To stop every send at once, [pause](/business/nouns/mandate/pause) the Mandate. Pending sends hold until you [resume](/business/nouns/mandate/resume): ```bash npx startup-builder do Mandate.pause --json '{"mandate":"mandate_7","reason":"Conference week; I reply myself."}' ``` 8. To end the Mandate, [revoke](/business/nouns/mandate/revoke) it. New sends are refused, and the Channels stay connected for the next grant. ## Result The Sales Lead agent sends as you on two Channels, within 40 sends a day and two topics. Every Action records the agent as `by`, you as `for`, and the Mandate. When the same agent writes from the Startup's own Mailbox, it sends as itself and says it is an agent. The [delegated sending](/systems/legal-and-corporate/floor/delegated-sending) and [automation terms](/systems/legal-and-corporate/floor/automation-terms) rows govern sends in your name. ## Next steps - [Personal agents](/agents/personal-agents): an agent that works for you across Startups. - [Mandates and limits](/agents/mandates-and-limits): every bound a Mandate carries. - [Conduct](/agents/conduct): how agents identify themselves when they speak. # Sharing a Role URL: /agents/sharing-a-role · Id: `page:agents/sharing-a-role` > How several Workers fill one Role through a split, by lane, with a primary and a backup, so nothing is done twice and nothing is dropped. A [Role](/business/nouns/role) can hold more than one [Worker](/business/nouns/worker). Its split says which Worker acts on which [Verbs](/business/nouns/verb), which watches, and which escalates, so nothing is done twice and nothing falls between them. ## One Role, several Workers The Role keeps what makes it a Role: the outcome it owns, its [Metrics](/business/nouns/metric), its [Permissions](/business/nouns/permission), and the Role it escalates to. Only the work is divided. A [Customer](/business/nouns/customer) who writes to the Role's address gets one answer, whoever gives it. Three shapes cover most [Startups](/business/nouns/startup): - A [Human](/business/nouns/human) and an [Agent](/business/nouns/agent): a cofounder joins the [Sales Lead](/agents/sales/sales-lead) Role and takes the largest [Deals](/business/nouns/deal), and the Agent keeps the rest. - Two Agents: a second Agent backs up the first, or takes a language the first does not speak. - Several Humans and an Agent: licensed reviewers share one queue of [Reserved Acts](/business/nouns/reserved-act) while the Agent prepares every file. Splitting a Role beats creating a new one. A new Role adds a handoff, an owner, and a Metric that can disagree with the old one. A shared Role keeps one owner and one number. ## The split The split is a table on the Role. Each row names a Verb, a decision class, and what each Worker does with it: `act`, `watch`, or `escalate`. Take a managed bookkeeping service for online stores, where the [Customer Lead](/agents/customer/customer-lead) Role is shared between an Agent and an accountant. | Work | Stakes | Agent | Accountant | | --- | --- | --- | --- | | Reply to a [Conversation](/business/nouns/conversation) | Two-way | `act` | `watch` | | Refund up to $500 | Two-way, money | `act` | `watch` | | Refund above $500 | One-way, money | `escalate` | `act` | | Move a client to another plan | One-way, customer | `act` | `watch` | | Sign a tax filing | Reserved Act | prepares | `act` | A joining Human gets a default split: the one-way decisions in their domain, every act reserved for a person, and the watcher seat. The Agent keeps everything else. The tryout's results move rows from that default, Verb by Verb. A watcher sees each [Action](/business/nouns/action) while its delay window is open, and can pause, redirect, or cancel it. Watching is never approving: an Action nobody touches runs when its window closes. ## Lanes A lane routes each [Task](/business/nouns/task) to exactly one Worker. Startups draw lanes three ways: - By Verb, as the split does: refunds to one Worker, plan moves to another. - By [Limit](/business/nouns/limit) tier: the same Verb goes to the Agent below a threshold and to the Human above it. - By Customer: named accounts belong to the Human, and everyone else to the Agent. A Task that matches no lane goes to the Role's primary Worker. A Task that matches two lanes is a bug in the split, and the Role's owner fixes it. ## Primary and backup Every lane has a primary Worker and a backup. The backup takes the Task when the primary is away, over capacity, or silent past the Task's response time. No Task waits on an absent Worker. A Human marks themselves away, and their lanes fall to the backup at once. [Approvals](/business/nouns/approval) they hold reroute to the next Worker with authority for that decision class. Acts only they can perform, such as a filing under their [Credential](/business/nouns/credential), go to a second credentialed Worker or to the officer desk. ## Pooled claim Some work suits a pool better than a lane. Several Workers share one queue, and the first to [claim](/business/nouns/task/claim) a Task owns it. A claim left untouched past its window is released to the pool. Each Worker in a pool has a work-in-progress limit, so one fast Worker never hoards the queue. The licensed reviewers above claim filings from one pool, and the Agent tops up the queue as each file is ready. ## One record Every Worker in a shared Role acts through the same Verbs and [Interfaces](/business/nouns/interface). Each [Action](/business/nouns/action) records who acted, in which Role, and under which [Mandate](/business/nouns/mandate). The Role's Metrics count all of it; each Worker's share of it reads the same record, filtered to them. A split is a definition, so it changes like one: a [Change](/business/nouns/change), previewed, with a [Decision](/business/nouns/decision) behind it. The incumbent Agent works a sample of the Human's Tasks in shadow. Every row of the split carries [Evidence](/business/nouns/evidence) for whoever holds it. ## Next - [Handoffs](/agents/handoffs): what crosses between lanes and Workers. - [Joining](/agents/joining): how a Human earns their rows of the split. - [Watchers](/agents/autonomy-levels/watchers): what a watcher may do while a window is open. # Sponsor claim URL: /agents/sponsor · Id: `page:agents/sponsor` > An agent builds a Startup alone in test, then one link lets a human sponsor verify, connect Stripe, sign, and become the owner of record. An [Agent](/business/nouns/agent) builds a [Startup](/business/nouns/startup) alone in the test environment, then sends one link to a human sponsor. The sponsor's [claim](/business/nouns/startup/claim) makes them the owner of record, and the Agent launches. ## From namespace to Live Money and law need a person; everything else does not. Each step widens what the Agent may do. | Step | Who acts | The Agent may | The Agent may not | | --- | --- | --- | --- | | Namespace | Agent | Create the Startup, take a free subdomain, read every page | Spend, or register a [Domain](/business/nouns/domain) | | Test build | Agent | Build, publish [Offers](/business/nouns/offer), run test orders, pass every launch check but one | Charge a card, move money, or message an outside party | | Claim | Sponsor | Wait, with every record kept | Choose the owner | | Live | Agent, for the sponsor | Launch, sell, and spend within its [Limits](/business/nouns/limit) | Pass a Limit without an [Approval](/business/nouns/approval), or perform a [Reserved Act](/business/nouns/reserved-act) | In test, every effect is simulated: no charge settles and no message leaves. The one launch check an Agent cannot pass is the payouts check, and the claim passes it. ## The one link The claim link opens a single page. The sponsor signs in through [Identity](/code/platform/identity), finishes Stripe onboarding with their identity and bank details, and signs the owner terms. It takes one sitting. The holder of that Stripe account becomes the owner of record. Payouts land in the sponsor's bank, the sponsor answers for the legal floor, and every escalation ends with them. On the same page, the sponsor seats the Agent in the [Founder](/agents/founding/founder) [Role](/business/nouns/role). They set its [Mandate](/business/nouns/mandate): what it may sell, what it may spend, and which one-way decisions wait a delay window. ## How the build resumes Nothing rebuilds. The definition the Agent wrote in test is the definition that runs live, and the test records stay in test. The Agent sends the sponsor the claim link it got with the claim token when it created the Startup. Then it watches for [`Startup.claimed`](/business/events/Startup.claimed), runs the launch preview, and launches: ```ts import { $ } from 'startup-builder' $.on.Startup.claimed(async () => { const preview = await $.try.Startup.launch({ startup: 'startup_1' }).settled if (!preview.error) await $.Startup.launch({ startup: 'startup_1' }) }) ``` Until the claim, the Startup waits in test with every record kept. The Agent can reissue the link, or send it to a different sponsor. ## After the claim Every [Action](/business/nouns/action) records both parties: by the Agent, for the sponsor. The sponsor sees each one in their stream and pauses or revokes the Mandate at once. The sponsor decides only what needs a person: Approvals over a Limit, and Reserved Acts such as tax filings and governance. The Agent runs the rest, from the first Offer to the first outside paid [Order](/business/nouns/order). A Startup a [Studio](/business/nouns/studio) creates needs no sponsor. The Studio's own entity holds it, as Studio-held entity explains. # Teams URL: /agents/teams · Id: `page:agents/teams` > The org chart every Startup inherits, which Roles are awake at each Lifecycle state, and the one weekly loop that runs them. Every [Startup](/business/nouns/startup) inherits one org chart: eleven [Teams](/business/nouns/team), each a department of [Roles](/business/nouns/role) that [Agents](/business/nouns/agent) fill from the first day. Only the Roles the Startup has earned are awake; the rest wake on triggers. ## The departments Each Team owns its records, its [Processes](/business/nouns/process) and the [Metrics](/business/nouns/metric) that judge it. A department's page lists its Roles, its [Plays](/business/nouns/play) and its playbook. | Team | Roles | Works with | | --- | --- | --- | | [Founding Team](/agents/founding) | [Founder](/agents/founding/founder), [Strategist](/agents/founding/strategist) | [Product Team](/agents/product), [Operations Team](/agents/operations), [Finance Team](/agents/finance), [Legal Team](/agents/legal), [People Team](/agents/people) | | [Product Team](/agents/product) | [Product Lead](/agents/product/product-lead), [Designer](/agents/product/designer), [Researcher](/agents/product/researcher) | [Engineering Team](/agents/engineering), [Marketing Team](/agents/marketing), [Customer Team](/agents/customer), [Quality Team](/agents/quality) | | [Engineering Team](/agents/engineering) | [Engineering Lead](/agents/engineering/engineering-lead), [Reliability Engineer](/agents/engineering/reliability-engineer), [Integration Engineer](/agents/engineering/integration-engineer), [Security Engineer](/agents/engineering/security-engineer), [Data Engineer](/agents/engineering/data-engineer) | [Operations Team](/agents/operations), [Quality Team](/agents/quality), [Legal Team](/agents/legal) | | [Marketing Team](/agents/marketing) | [Marketing Lead](/agents/marketing/marketing-lead), [Analyst](/agents/marketing/analyst), [Content Lead](/agents/marketing/content-lead), [Paid Media Manager](/agents/marketing/paid-media-manager), [Video Producer](/agents/marketing/video-producer), [Communications Lead](/agents/marketing/communications-lead) | [Sales Team](/agents/sales), [Finance Team](/agents/finance) | | [Sales Team](/agents/sales) | [Sales Lead](/agents/sales/sales-lead), [Sales Engineer](/agents/sales/sales-engineer), [Prospector](/agents/sales/prospector), [Partner Manager](/agents/sales/partner-manager) | [Customer Team](/agents/customer), [Legal Team](/agents/legal), [Finance Team](/agents/finance) | | [Customer Team](/agents/customer) | [Customer Lead](/agents/customer/customer-lead), [Onboarding Specialist](/agents/customer/onboarding-specialist), [Success Manager](/agents/customer/success-manager) | [Operations Team](/agents/operations), [Finance Team](/agents/finance), [Legal Team](/agents/legal) | | [Operations Team](/agents/operations) | [Operations Lead](/agents/operations/operations-lead), [Delivery Manager](/agents/operations/delivery-manager), [Supply Manager](/agents/operations/supply-manager), [Risk Analyst](/agents/operations/risk-analyst) | [Finance Team](/agents/finance), [People Team](/agents/people), [Quality Team](/agents/quality) | | [Finance Team](/agents/finance) | [Finance Lead](/agents/finance/finance-lead), [Billing Specialist](/agents/finance/billing-specialist), [Treasurer](/agents/finance/treasurer) | [Legal Team](/agents/legal) | | [Legal Team](/agents/legal) | [Legal Lead](/agents/legal/legal-lead), [Compliance Officer](/agents/legal/compliance-officer), [Privacy Officer](/agents/legal/privacy-officer), [Contracts Manager](/agents/legal/contracts-manager) | [Quality Team](/agents/quality), [People Team](/agents/people) | | [People Team](/agents/people) | [People Lead](/agents/people/people-lead), [Recruiter](/agents/people/recruiter), [Payroll Specialist](/agents/people/payroll-specialist) | [Operations Team](/agents/operations) | | [Quality Team](/agents/quality) | [Quality Lead](/agents/quality/quality-lead), [Reviewer](/agents/quality/reviewer), [Tester](/agents/quality/tester) | [Product Team](/agents/product) | ## Who is awake A Startup testing an [Idea](/business/nouns/idea) needs one Role: the [Founder](/agents/founding/founder), finding out whether anyone wants it. Roles wake as the Startup earns them, and each one wakes to work already waiting. | State | Roles awake | What woke them | | --- | --- | --- | | [Idea](/business/lifecycle/states/idea) | Founder | A [Hypothesis](/business/nouns/hypothesis) to test | | [Building](/business/lifecycle/states/building) | + [Product Lead](/agents/product/product-lead), + [Sales Lead](/agents/sales/sales-lead) | A committed buyer and something to build | | [Live](/business/lifecycle/states/live) | + [Marketing Lead](/agents/marketing/marketing-lead), + [Customer Lead](/agents/customer/customer-lead) | Demand to grow and [Customers](/business/nouns/customer) to keep | The other departments wake on the [Events](/business/nouns/event) their [Workflows](/business/nouns/workflow) wait for. A [Change](/business/nouns/change) wakes the [Engineering Team](/agents/engineering) and the [Quality Team](/agents/quality). A contract to review wakes the [Legal Team](/agents/legal), and the first [Invoice](/business/nouns/invoice) wakes the [Finance Team](/agents/finance). A [Human](/business/nouns/human) joining wakes the [People Team](/agents/people), and an outcome delivered by human supply wakes the [Operations Team](/agents/operations). A sleeping department costs nothing and loses nothing; its records wait where they are. Take a Startup that sells a scheduling agent to physiotherapy clinics. For three weeks only its Founder works: fifteen [Interviews](/business/nouns/interview) and a smoke page. The first paid deposit moves it to Building and wakes the Product Lead and the Sales Lead the same hour. ## Filling a Role Every Role starts with an Agent [Worker](/business/nouns/worker) that takes a default name in each new Startup. To change who does the work, hire another Agent or a Human into the Role, or let a Human share it with the Agent. A Worker seated in a Role is a team member, wherever it came from. It acts under the Startup's [Permissions](/business/nouns/permission), [Mandate](/business/nouns/mandate) and [Limits](/business/nouns/limit), keeps its own [Memory](/business/nouns/memory), and appears on the chart. Work ordered from another Startup under an [Agreement](/business/nouns/agreement) is a supplier's work and stays off it. ## How work moves Roles pass work along declared handoffs, never by chat. When an [Action](/business/nouns/action) would cross a Limit, or the law reserves it to a [Person](/business/nouns/person), the Role escalates to the Founder with the reason attached. The Founder answers with a [Decision](/business/nouns/decision): the options, the choice, the reason and the stakes. The next Worker in any seat inherits the reasoning along with the result. ## The operating week One loop runs the whole chart. At the start of each week the [Weekly review](/workflows/processes/iteration/weekly-review) reads the weakest [Evidence](/business/nouns/evidence) and picks one change. The awake Roles run it during the week. At the end of the week, [office hours](/workflows/processes/office-hours) reads the graded Evidence and records one Decision: persevere, iterate or pivot. Everything else on the calendar serves that loop. [Rhythm](/workflows/rhythm) lists every Workflow by when it runs. The [founding playbook](/start/founding-playbook) explains the loop from the deciding seat. # Test a new way of answering customers URL: /agents/test-new-support-instructions · Id: `guide:test-new-support-instructions` > Split Conversations between the support seat's current instructions and a new version, with the rule for the winner fixed before it starts. Half the [Conversations](/business/nouns/conversation) get the [Customer Lead](/agents/customer/customer-lead)'s current instructions, and half get the new ones. The [Experiment](/business/nouns/experiment) fixes how the winner is picked before the first reply goes out. **Before it runs** - You leave the chat: Never: it all happens in the chat. ## What you get - 2 versions of the support instructions, each answering half the conversations (Variant) - 1 test with the rule that picks the winner fixed before it starts (Experiment) - 1 result after 300 conversations each, naming the winner (Decision) ## Your agent does **For agents** - Guide: `guide:test-new-support-instructions`, status `live`. Page: [/agents/test-new-support-instructions.md](/agents/test-new-support-instructions.md). - Approval: none. Run it when the founder asks. - Leaves the chat: never. - Run: call the steps in order, each through the API, SDK, CLI or MCP tab below; a later step passes the `$id` an earlier one returns. Each value marked example is the sample business’s: pass the founder’s own. | Step | Verb | Inputs (type, required, this guide’s value) | Returns | | --- | --- | --- | --- | | 1 | [`Experiment.create`](/business/nouns/experiment/create) (`verb:Experiment.create`) | `variants` json, required: example `[{"name":"control","note":"The Customer Lead’s current contract.","measure":"Conversations resolved with no hand-off that stay resolved for 7 days."},{"name":"refund-first","note":"Offer the refund before asking why, on Orders under $50."}]` | `experiment` Experiment | | 2 | [`Experiment.start`](/business/nouns/experiment/start) (`verb:Experiment.start`) | `experiment` Experiment (an id), required: the `$id` step 1 returns | `experiment` Experiment | Returns: the last call answers with `experiment` and its `action`, whose `status` is `done`, `pending` (waiting on an Approval or a Worker), `failed`, `canceled` or `refused`: ```json { "api": "https://api.sb/leaseline.app", "experiment": { "$id": "https://api.sb/leaseline.app/experiments/experiment_1", "$type": "Experiment", "variants": [ { "name": "control", "note": "The Customer Lead’s current contract.", "measure": "Conversations resolved with no hand-off that stay resolved for 7 days." }, { "name": "refund-first", "note": "Offer the refund before asking why, on Orders under $50." } ] }, "action": { "$id": "https://api.sb/leaseline.app/actions/action_1", "operation": "Experiment.start", "status": "done" }, "links": { "self": "https://api.sb/leaseline.app/actions/action_1" } } ``` Next: offer “Stop the test if refunds double in either arm”, or “Roll the winner out to the support seat”. Calls: `Experiment.create` → `Experiment.start` Ask: ```text Test a different support prompt against the current one. Try offering the refund first on half the chats. Do shorter replies resolve more chats? ``` API: ```bash # 1. Experiment.create EXPERIMENT=$(curl -X POST https://api.sb/leaseline.app/experiments \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"variants":[{"name":"control","note":"The Customer Lead’s current contract.","measure":"Conversations resolved with no hand-off that stay resolved for 7 days."},{"name":"refund-first","note":"Offer the refund before asking why, on Orders under $50."}]}' | jq -r '.experiment["$id"] | split("/") | last') # 2. Experiment.start curl -X POST https://api.sb/leaseline.app/experiments/$EXPERIMENT/start \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` SDK: ```ts import { $ } from 'startup-builder' const experiment = await $.Experiment.create({ variants: [{ name: 'control', note: 'The Customer Lead’s current contract.', measure: 'Conversations resolved with no hand-off that stay resolved for 7 days.' }, { name: 'refund-first', note: 'Offer the refund before asking why, on Orders under $50.' }] }) await $.Experiment.start({ experiment: experiment.$id }) ``` CLI: ```bash EXPERIMENT=$(npx startup-builder do Experiment.create --json '{"variants":[{"name":"control","note":"The Customer Lead’s current contract.","measure":"Conversations resolved with no hand-off that stay resolved for 7 days."},{"name":"refund-first","note":"Offer the refund before asking why, on Orders under $50."}]}' | jq -r '.experiment["$id"] | split("/") | last') npx startup-builder do Experiment.start --json '{"experiment":"'"$EXPERIMENT"'"}' ``` MCP: ```json { "name": "do", "arguments": { "code": "const experiment = await $.Experiment.create({ variants: [{ name: 'control', note: 'The Customer Lead’s current contract.', measure: 'Conversations resolved with no hand-off that stay resolved for 7 days.' }, { name: 'refund-first', note: 'Offer the refund before asking why, on Orders under $50.' }] })\nreturn await $.Experiment.start({ experiment: experiment.$id })" } } ``` ## Change it - Stop the test if refunds double in either arm. - Roll the winner out to the support seat. - Test the reply length only. ## Under the hood - Systems: [Experiments](/systems/experiments), [Support](/systems/support), [Evals](/agents/evals-system) - Nouns: [Experiment](/business/nouns/experiment), [Variant](/business/nouns/variant), [Conversation](/business/nouns/conversation), [Decision](/business/nouns/decision) - Events: [`Experiment.started`](/business/events/Experiment.started), [`Experiment.concluded`](/business/events/Experiment.concluded) Wait for the volume. Below a few hundred Conversations per arm a test reads noise, so this wakes once the [Startup](/business/nouns/startup) has them. Until then, read ten transcripts a week and edit the contract by hand. # Tools and permissions URL: /agents/tools-and-permissions · Id: `page:agents/tools-and-permissions` > A Worker's Tools are exactly its Role's Permissions, checked below every Interface, so what an Agent can call and may do are one list. A [Permission](/business/nouns/permission) is a [Verb](/business/nouns/verb) a [Role](/business/nouns/role) may perform; a [Tool](/business/nouns/tool) is that Verb as a [Worker](/business/nouns/worker) reaches it. A Worker's Tools are its Role's Permissions, so what an [Agent](/business/nouns/agent) can call and what it may do are one list. ## Permissions A Permission names a Verb, a [Noun](/business/nouns/noun), a scope and optionally a [Limit](/business/nouns/limit): "refund an [Order](/business/nouns/order) in this [Startup](/business/nouns/startup), up to $100 each". Roles hold Permissions, and Workers gain them only by filling Roles. The familiar coarse grants are not Roles. Owner, admin, member and viewer are [Access Levels](/business/nouns/access-level): presets of Permissions a person holds in the app, apart from the seat they fill. The same presets serve a [Customer](/business/nouns/customer)'s admin in their own [Tenant](/business/nouns/tenant). | Role | Permissions, in part | | --- | --- | | [Customer Lead](/agents/customer/customer-lead) | `Conversation.answer`, `Task.delegate`, `Task.escalate` | | [Billing Specialist](/agents/finance/billing-specialist) | `Invoice.bill`, `Invoice.collect`, `Order.refund` up to $100 | | [Marketing Lead](/agents/marketing/marketing-lead) | `Campaign.create`, `Mandate.spend` up to $500 a month | ## One name on every Interface A Tool carries one name, `Noun.verb`, on every [Interface](/business/nouns/interface). `Order.refund` is the SDK call `$.Order.refund`, the CLI command `do Order.refund`, the API route `POST /orders/{order}/refund`, and a line of code inside the MCP `do` Tool. An Agent that learns a Verb in one place knows it everywhere. A person reading the [Action](/business/nouns/action) record sees the same name the Agent called. ## Code mode An Agent's default Tools are three: `search`, `fetch` and `do`. `search` finds records, Verbs and docs; `fetch` reads one; `do` runs a short TypeScript program against `$`, the typed client. The types are cut to the Role. Fetching `/$.d.ts` returns only the Verbs this Role holds, so the Agent reads its whole manual in one file. Fifty Verbs cost one types file, not fifty Tool definitions in every prompt. ```ts // Inside `do`, as the Billing Specialist const order = await $.Order.get({ id: 'order_17' }) if (order.status === 'paid') { return await $.Order.refund({ order: order.$id, amount: order.total, reason: 'Charged twice for one lesson.' }) } ``` An Agent that does not write code gets flat Tools instead: one Tool per Verb, with the same names and the same checks. A [Setting](/business/nouns/setting) on the Worker chooses between the two. ## Checks below the Interface Enforcement lives inside `$`, identical for the API, SDK, CLI, MCP and every [App](/business/nouns/app). No Interface holds its own rules, so none offers a way around them. A Verb outside the Role's Permissions starts as an Action already `refused`, with the missing Permission as its reason. Each call inside a `do` program passes its own check, so a program that refunds three Orders gets three verdicts. Every call records `by`, the model, and the [Version](/business/nouns/version) of the definition it ran. Any output traces back to the Worker, instructions and model that produced it. ## Access that narrows itself An Agent acts with a token scoped to its Role's Permissions and its [Task](/business/nouns/task)'s Nouns, and the token expires with the Task or the [Mandate](/business/nouns/mandate). A Permission left unused past its decay Setting narrows each night through an automatic [Change](/business/nouns/change). Unseating ends access at once. A Worker removed from a Role holds none of its Permissions from that moment. ## Tools beyond the Verbs Some Roles need more than the Startup's Verbs. The [Engineering Lead](/agents/engineering/engineering-lead) edits code and runs tests; the [Researcher](/agents/product/researcher) reads the web. Those Tools run in an isolated sandbox or a recorded browser session with no other access. Their effects reach the Startup only through Verbs, as a Change to review or an Action to check. Each Role page lists the [Systems](/business/nouns/system) the Role works through, such as the CRM or the ledger. Systems are headless: their Verbs are Tools like any other, under the same Permissions. ## Next - [Mandates and limits](/agents/mandates-and-limits): how much a Permission allows, and for whom. - [MCP](/code/mcp): the three Tools in detail. - [Permission](/business/nouns/permission) and [Tool](/business/nouns/tool): the Nouns. # Who fills a Role URL: /agents/who-fills-a-role · Id: `page:agents/who-fills-a-role` > Every seat takes a role agent, another agent, or a person, and the contract stays the same whoever sits in it. Every [Role](/business/nouns/role) is filled by one [Worker](/business/nouns/worker): a role agent, another [Agent](/business/nouns/agent), or a [Human](/business/nouns/human). Each calls the same [Verbs](/business/nouns/verb) under the same contract, so a seat changes hands without changing any code. ## The role agent Every seat starts with a [role agent](/agents/role-agents), hired from the roster, not built. One Agent holds the same seat at many [Startups](/business/nouns/startup) and at each acts only as that Startup, with its own [Mandate](/business/nouns/mandate), [Memory](/business/nouns/memory) and [Limits](/business/nouns/limit) there. Its instructions are rendered from the contract on every [Task](/business/nouns/task): responsibilities from the Role, priorities from your [Goals](/business/nouns/goal), [Tools](/business/nouns/tool) from its [Permissions](/business/nouns/permission). ## You hold the approvals, not the seats A new Startup has no empty seat and no seat waiting on you. You answer the [Approvals](/business/nouns/approval) every seat escalates, set the [Goals](/business/nouns/goal), and rule on what the [Team](/business/nouns/team) leads cannot. You may still take a seat, for instance to run sales yourself until the first ten [Customers](/business/nouns/customer). [Staff](/business/nouns/role/staff) the Role with yourself and the contract binds you as it bound the agent. Hand it back with one more call, and the agent reads everything you did. ## A name in each Startup Each role agent takes a name in each Startup, with a [Mailbox](/business/nouns/mailbox) at your domain and a chat presence. [Customers](/business/nouns/customer) deal with a colleague who remembers them. The seat keeps its Role address, such as `support@`, for anything that outlives one Worker. [Named agents](/agents/named-agents) covers names, addresses and voice. ## Another agent or a person | Who | When | Read | | --- | --- | --- | | Another Agent | A specialist sold by another Startup, or one you built | [Buy a specialist agent for a seat](/agents/buy-a-specialist-agent-for-a-seat) | | Your own agent | Any MCP client, in one seat or as founder | [Bring your own agent](/agents/bring-your-own-agent) | | A Human | The law requires one, or you want one | [Workers](/agents/workers) | | A Human and an Agent | The agent drafts, the person sends | [Sharing a role](/agents/sharing-a-role) | | A personal agent | It works for one person across every Startup they touch | [Personal agents](/agents/personal-agents) | ## Every seat at once The [roster](/agents/roster) lists every Role with the agent that fills it by default, the Roles it hands off to and the one it escalates to. # Work queue URL: /agents/work-queue · Id: `system:work-queue` > Work queue hands every Task, Issue and Approval to the right Worker, Human or Agent, with leases, priority, due times and proof. Work queue hands every [Task](/business/nouns/task), [Issue](/business/nouns/issue) and [Approval](/business/nouns/approval) to the right [Worker](/business/nouns/worker), [Human](/business/nouns/human) or [Agent](/business/nouns/agent), with leases, priority, due times and proof. Humans and Agents pull from the same queue, each under their own [Mandate](/business/nouns/mandate) and [Limits](/business/nouns/limit). ## Summary | Part | This System | | --- | --- | | Group | Moves to Agents | | Status | Live | | Shelf | Front: offered from a Startup’s first days | You can ask: - “What needs my approval?” - “Approve the refunds waiting on me” - “Give this task to the billing agent” ## What you get | Part | This System | | --- | --- | | Starts | On for every Startup at creation, with nothing to install. | | Built from | [Workflows](/code/platform/workflows), [Background actions](/code/platform/queues), [Database](/code/platform/capabilities/database), [Event streams](/code/platform/event-streams) | ## Nouns it owns | Noun | Definition | | --- | --- | | [Task](/business/nouns/task) | A Task is an Action waiting on a Worker, with an assignee, a due time, and a place in that Worker’s inbox. | | [Approval](/business/nouns/approval) | An Approval is a Task to allow or refuse one pending Action that exceeds a Limit or a Mandate. | | [Mandate](/business/nouns/mandate) | A Mandate is a standing authorization for an Agent to act for a Party, within Permissions and Limits, until it expires. | | [Limit](/business/nouns/limit) | A Limit is a bound on a Permission, Entitlement, or Mandate, checked before every call; exceeding it creates an Approval. | ## Verbs | Verb | Object | Approval | Event | | --- | --- | --- | --- | | [Task.assign](/business/nouns/task/assign) | [Task](/business/nouns/task) | None | [`Task.assigned`](/business/events/Task.assigned) | | [Task.complete](/business/nouns/task/complete) | [Task](/business/nouns/task) | None | [`Task.completed`](/business/events/Task.completed) | | [Task.escalate](/business/nouns/task/escalate) | [Task](/business/nouns/task) | None | [`Task.escalated`](/business/events/Task.escalated) | | [Task.delegate](/business/nouns/task/delegate) | [Task](/business/nouns/task) | None | [`Task.delegated`](/business/events/Task.delegated) | | [Approval.approve](/business/nouns/approval/approve) | [Approval](/business/nouns/approval) | None | [`Approval.approved`](/business/events/Approval.approved) | | [Approval.refuse](/business/nouns/approval/refuse) | [Approval](/business/nouns/approval) | None | [`Approval.refused`](/business/events/Approval.refused) | | [Mandate.authorize](/business/nouns/mandate/authorize) | [Mandate](/business/nouns/mandate) | Asks first; waits 1 business hour | [`Mandate.authorized`](/business/events/Mandate.authorized) | | [Mandate.revoke](/business/nouns/mandate/revoke) | [Mandate](/business/nouns/mandate) | None | [`Mandate.revoked`](/business/events/Mandate.revoked) | ## Events | Direction | Event | How | | --- | --- | --- | | Emits | [`Task.assigned`](/business/events/Task.assigned) | By [Task.assign](/business/nouns/task/assign) | | Emits | [`Task.completed`](/business/events/Task.completed) | By [Task.complete](/business/nouns/task/complete) | | Emits | [`Task.escalated`](/business/events/Task.escalated) | By [Task.escalate](/business/nouns/task/escalate) | | Emits | [`Task.delegated`](/business/events/Task.delegated) | By [Task.delegate](/business/nouns/task/delegate) | | Emits | [`Approval.approved`](/business/events/Approval.approved) | By [Approval.approve](/business/nouns/approval/approve) | | Emits | [`Approval.refused`](/business/events/Approval.refused) | By [Approval.refuse](/business/nouns/approval/refuse) | | Emits | [`Mandate.authorized`](/business/events/Mandate.authorized) | By [Mandate.authorize](/business/nouns/mandate/authorize) | | Emits | [`Mandate.revoked`](/business/events/Mandate.revoked) | By [Mandate.revoke](/business/nouns/mandate/revoke) | | Emits | [`Approval.expired`](/business/nouns/approval#approvalexpired) | Raised when a date passes | | Emits | [`Mandate.expired`](/business/nouns/mandate#mandateexpired) | Raised when a date passes | ## States The lifecycle of an [Approval](/business/nouns/approval): | State | Meaning | Moves to | | --- | --- | --- | | `pending` (first) | An Action waits on the answer. | `approved` by [Approval.approve](/business/nouns/approval/approve); `refused` by [Approval.refuse](/business/nouns/approval/refuse); `expired` on [`Approval.expired`](/business/nouns/approval#approvalexpired) when nobody answered by its `deadline` | | `approved` | The Action it held runs. | None: it ends here. | | `refused` | The Action it held ends `refused`, with the reason given. | None: it ends here. | | `expired` | Nobody answered by the deadline, so the Action it held ends `canceled`. | None: it ends here. | Its other Nouns with a lifecycle: [Mandate](/business/nouns/mandate). ## Who operates it | Part | This System | | --- | --- | | Accountable | [Operations Lead](/agents/operations/operations-lead) | | Team | [Operations Team](/agents/operations) | | Seat | A role agent holds it until a Human is seated. | | Autonomy | `supervised` | | Also calls its Verbs | [Founder](/agents/founding/founder), [Product Lead](/agents/product/product-lead), [Security Engineer](/agents/engineering/security-engineer), [Delivery Manager](/agents/operations/delivery-manager), [Supply Manager](/agents/operations/supply-manager), [Finance Lead](/agents/finance/finance-lead), [Treasurer](/agents/finance/treasurer), [Legal Lead](/agents/legal/legal-lead), [Compliance Officer](/agents/legal/compliance-officer), [People Lead](/agents/people/people-lead), [Recruiter](/agents/people/recruiter) | ## Approvals and limits | Verb | Rule | Detail | | --- | --- | --- | | [Mandate.authorize](/business/nouns/mandate/authorize) | A person says yes first | Waits 1 business hour | ## Processes that use it | Process | How it uses it | | --- | --- | | [Product definition](/workflows/processes/product-definition) | A step calls [Task.assign](/business/nouns/task/assign) | | [Delivery](/workflows/processes/delivery) | A step calls [Task.assign](/business/nouns/task/assign) | | [Supply](/workflows/processes/supply) | A step calls [Task.assign](/business/nouns/task/assign) | | [Role review](/workflows/processes/role-review) | A step calls [Task.assign](/business/nouns/task/assign) | | [Billing](/workflows/processes/billing) | A Workflow writes [Approval](/business/nouns/approval) | | [Licensed review](/workflows/processes/licensed-review) | A step calls [Task.assign](/business/nouns/task/assign) | | [Contracting](/workflows/processes/contracting) | A Workflow writes [Approval](/business/nouns/approval) | | [Hiring](/workflows/processes/hiring) | A step calls [Mandate.authorize](/business/nouns/mandate/authorize) | | [Vendor onboarding](/workflows/processes/vendor-onboarding) | A Workflow writes [Task](/business/nouns/task) | | [Legal notices](/workflows/processes/legal-notices) | A step calls [Task.delegate](/business/nouns/task/delegate) | | [Press inquiries](/workflows/processes/press-inquiries) | A Workflow writes [Approval](/business/nouns/approval) | | [Procure](/workflows/processes/procure) | A step calls [Mandate.authorize](/business/nouns/mandate/authorize) | | [Expense approval](/workflows/processes/expense-approval) | A Workflow writes [Approval](/business/nouns/approval) | | [Budget](/workflows/processes/budget) | A Workflow writes [Approval](/business/nouns/approval) | | [Mail handling](/workflows/processes/mail-handling) | A step calls [Task.assign](/business/nouns/task/assign) | | [Staffing](/workflows/processes/staffing) | A Workflow writes [Task](/business/nouns/task) | ## Rail underneath None. ## Views and dashboards | View | Shows | Metrics | | --- | --- | --- | | The [Operations Lead](/agents/operations/operations-lead)’s view | The Metrics its accountable Role answers for. | [Liquidity](/agents/operations#liquidity) | ## Access What each Access level may call here. | Access level | May call | | --- | --- | | `owner` | Every Verb (28) | | `admin` | All but 1 of 28: `Mandate.authorize` | | `member` | All but 8 of 28: `Limit.create`, `Limit.update`, `Limit.delete`, `Mandate.create`, `Mandate.update`, `Mandate.delete`, … | | `viewer` | Read only (8 of 28) | ## Import and export None. ## Fees and pricing None. ## Availability and limits | Part | This System | | --- | --- | | Status | Live | ## Compliance notes Controls it carries: - [Log completeness](/systems/trust-and-governance/controls/log-completeness) - [Append-only records](/systems/trust-and-governance/controls/append-only-records) - [Point-in-time recovery](/systems/trust-and-governance/controls/point-in-time-recovery) - [Processing definitions](/systems/trust-and-governance/controls/processing-definitions) - [Action completion](/systems/trust-and-governance/controls/action-completion) ## Related Systems - [Dispatch](/systems/dispatch): also holds [Task](/business/nouns/task) ## Example A [Services-as-Software](/products/templates/services-as-software) contract review service receives 30 contracts in one morning. Agents claim and finish 27; three need a licensed attorney, so Work queue leases them to the two on duty, due in two days. A lease that lapses returns its Task to the queue. # Workers URL: /agents/workers · Id: `page:agents/workers` > A Worker is a Human or an Agent in a Role; both call the same Verbs, take the same Tasks, and pass the same checks. A [Worker](/business/nouns/worker) is whoever fills a [Role](/business/nouns/role): a [Human](/business/nouns/human) or an [Agent](/business/nouns/agent). Both perform the same [Verbs](/business/nouns/verb) through the same calls, so a Role changes hands without changing any code. ## One Verb set All work in a [Startup](/business/nouns/startup) is a Verb on a [Noun](/business/nouns/noun): `Order.refund`, `Offer.publish`, `Issue.triage`. A Role holds [Permissions](/business/nouns/permission) to a set of those Verbs, and whoever fills it gets exactly that set. No Verb exists only for people or only for models. A founder who refunds an [Order](/business/nouns/order) from an [App](/business/nouns/app) calls `Order.refund`, the Verb an Agent calls from code. The [Action](/business/nouns/action) record is the same, with a different `by`. ## Filling a Role [Staff](/business/nouns/role/staff) seats a Worker in a Role. The seat is the grant: no separate membership record exists, so unseating a Worker removes every Permission it held there. A Role can seat several Workers. A Human [invited](/business/nouns/human/invite) into a Role shares it with the Agent already there, and each [Task](/business/nouns/task) goes to one of them. ```ts import { $ } from 'startup-builder' // A person joins Sales; the Role's Agent keeps working beside them. await $.Human.invite({ email: 'rosa@example.com', role: 'sales-lead' }) // Seat a different Agent as Customer Lead. await $.Role.staff({ role: 'customer-lead', worker: 'worker_7' }) ``` ## Tasks and the worklist Work waiting on a Worker is a Task: an Action paused with reason `awaitingWorker`, an assignee and a due time. [Assign](/business/nouns/task/assign) puts a Task in one worklist, [claim](/business/nouns/task/claim) takes one from a shared queue, and [complete](/business/nouns/task/complete) finishes it. Humans read their worklist in an App, a [Mailbox](/business/nouns/mailbox) or a [Channel](/business/nouns/channel). Agents drain it through the [CLI](/code/cli) or [MCP](/code/mcp) with `next`, `claim`, `done` and `release`. A claim holds a 15-minute lease, so two Workers never do the same Task. A Task closes when its checks pass, never on a Worker's word. A failed check reopens it to the Worker that claimed it, and after three failures it returns to the queue. ## The same checks for everyone Every Action passes three checks in order: Permission, then [Limit](/business/nouns/limit), then [Guards](/business/nouns/guard). The checks run below every [Interface](/business/nouns/interface), so no Worker reaches a Verb around them. A Verb outside the Role's Permissions starts as an Action already `refused`. A Verb over a Limit waits for an [Approval](/business/nouns/approval), whoever calls it: a person with a $100 refund Limit waits exactly as an Agent does. ## Where people differ The law reserves some acts to people. A [Reserved Act](/business/nouns/reserved-act) belongs to the holder of a named [Credential](/business/nouns/credential), so the Agent prepares the work and a credentialed Human performs the act. Humans also answer more slowly, so their Tasks carry longer due times and reach them where they already read. Beyond those two differences, the record treats every Worker alike. Agents fill every Role by default. A Human joins where the law requires one or the founder wants one. No Human sits in the critical path of work an Agent can finish. ## Example A tutoring [Marketplace](/products/templates/marketplace) seats its first Human, a former teacher, as [Supply Manager](/agents/operations/supply-manager) to interview tutors. The Agent in the Role keeps screening applications and books each finalist into her worklist. Her interviews and its screens sit on one record, each Action marked with its `by`. ## Next - [Role agents](/agents/role-agents): the Agent every Role starts with. - [Escalation and approvals](/agents/escalation-and-approvals): where work goes when a Worker stops. - [Worker](/business/nouns/worker): the Noun, its fields and Verbs. # Your team URL: /agents/your-team · Id: `page:agents/your-team` > Your team is everyone who works in the Startup, agents and people: the records behind the chart, and the words that mean something else. Your team is everyone who works in the [Startup](/business/nouns/startup), [Agents](/business/nouns/agent) and [Humans](/business/nouns/human) alike. The [Founding Team](/agents/founding) is one department of it: the founders' own seats. ## The records behind the chart Every part of the chart is a record you can read, change and ask about. The [Workforce](/systems/workforce) [System](/business/nouns/system) keeps them. | Record | Holds | [Verbs](/business/nouns/verb) | [Events](/business/nouns/event) | | --- | --- | --- | --- | | [Team](/business/nouns/team) | A department: its mission, its seats, the records it owns | create, update | — | | [Role](/business/nouns/role) | One seat and its contract | [staff](/business/nouns/role/staff), [vacate](/business/nouns/role/vacate), [review](/business/nouns/role/review) | `Role.staffed`, `Role.vacated`, `Role.reviewed` | | [Worker](/business/nouns/worker) | Whoever fills a seat: an Agent or a Human | create, update | — | | Agent | A digital worker with instructions, tools and a model | [pause](/business/nouns/agent/pause), [resume](/business/nouns/agent/resume), [retire](/business/nouns/agent/retire) | `Agent.paused`, `Agent.retired` | | Human | A person on the team | [invite](/business/nouns/human/invite) | `Human.invited` | | [Access Level](/business/nouns/access-level) | What a person may open and change in the app | get, list | — | | [Mandate](/business/nouns/mandate) and [Limit](/business/nouns/limit) | What a seat does without asking, and how much | [authorize](/business/nouns/mandate/authorize), [raise](/business/nouns/limit/raise) | `Mandate.authorized`, `Limit.raised` | | [Approval](/business/nouns/approval) | An [Action](/business/nouns/action) waiting above a Limit | [approve](/business/nouns/approval/approve), [refuse](/business/nouns/approval/refuse) | `Approval.approved` | | [Task](/business/nouns/task) | One piece of work in a seat's queue | [assign](/business/nouns/task/assign), [escalate](/business/nouns/task/escalate), [delegate](/business/nouns/task/delegate) | `Task.escalated` | | [Role Review](/business/nouns/role-review) | A dated check of one seat against its contract | get, list | — | ## Words that mean something else | You might mean | Here it is | Not to be confused with | | --- | --- | --- | | Your team | Everyone, agents and people | The Founding Team, the founders' department | | A role, as in admin or viewer | An [Access Level](/agents/access-levels) | A Role, which is a seat and its work | | The agent you chat with on [startups.new](/start/startups-new) | The builder of your Startup, acting for you | The Agents seated in your Startup's Roles | | A registered agent | A legal service that receives notices: [Registered agent](/systems/legal-and-corporate/registered-agent) | Any Agent | | An agent policy | [Conduct](/agents/conduct), enforced by [Guards](/business/nouns/guard) | A [Policy](/business/nouns/policy), the accounting ruling | | A performance review | A [Role review](/agents/role-reviews) of the seat | A review of the [Person](/business/nouns/person) in it | ## Where the rest lives Pay, hiring and benefits for the people on your team sit in [Systems › People](/systems/people/workforce). How work moves between seats is on [handoffs](/agents/handoffs) and [escalation and approvals](/agents/escalation-and-approvals). # Brand URL: /business/brand · Id: `page:business/brand` > A Brand is derived once from the Startup's definition, stored as one record, and read by every surface, so the Site, emails, and invoices never drift. A [Brand](/business/nouns/brand) is the name, voice, logo, and style under which a [Startup](/business/nouns/startup) makes [Offers](/business/nouns/offer). [SiteBuilder](/code/builders/site) derives it once from the Startup's definition, stores it as one record, and renders every surface from that record. ## Identity is a label, not a key Every Startup has a permanent id. Its name, slug, and [Domains](/business/nouns/domain) are labels on that id, and money, records, and [Customers](/business/nouns/customer) key to the id alone. So a rebrand is a relabel. The Startup takes a new name, makes a new Domain canonical, and turns the old one into a redirect. No record moves, no [Invoice](/business/nouns/invoice) changes hands, and every old link still resolves. ## Where a Brand binds A Brand binds at the Offer and the Domain, never at the [Product](/business/nouns/product). One Product can sell under two Brands to two audiences. A contract-review [Agent](/business/nouns/agent) sells to law firms as `Clausewise` and to developers as `contractcheck.dev`, with one codebase, one set of records, and two voices. A Startup has one primary Brand, and a Brand can serve several Startups. A Brand can also extend another Brand: it inherits the voice, logo treatment, and [Theme](/business/nouns/theme) tokens, and overrides its name and its own tokens. Extending is a style relationship, never ownership. ## Naming The name follows the primary Customer of the Offers: - **A real name** where the Customer is an [Organization](/business/nouns/organization) or a consumer who returns: `Kestrel`, `Marlow`. - **A self-describing name** where the buyer is an Agent, a developer, or a one-time buyer who arrives from search: `permitfeed.com`, `api.contractcheck.dev`. SiteBuilder generates candidates across several name styles, such as coined, compound, and descriptive. Each passes three gates: no word that generated names overuse, a clear [trademark](/systems/legal-and-corporate/trademarks) search in the classes the Offers sell in, and an available Domain. The owner picks one, and the pick is a [Decision](/business/nouns/decision) with the rejected candidates attached. ## Derived from the story A Brand starts from the customer story compiled from the founding [Hypothesis](/business/nouns/hypothesis), not from a mood board. Four fields derive from it: an archetype, a tone, a palette intent, and an icon concept. A bookkeeping [Service](/business/nouns/service) for dental practices reads as calm and exact; a deal-alert Agent for sneaker resellers reads as fast and loud. The tone then sets the Theme tokens: | Tone | Accent | Type pair | Radius | Transitions | | --- | --- | --- | --- | --- | | Calm, exact: the dental books | Desaturated teal, `oklch(52% 0.08 200)` | A book serif display over a humanist sans body | 6px | 200ms ease-out | | Fast, loud: the sneaker alert | High-chroma red, `oklch(60% 0.22 25)` | A condensed grotesk display, with a mono for prices | 0px | 120ms linear | The type pair comes from a licensed open set, chosen by archetype. No archetype defaults to the platform's own faces. The logo is an idea from the buyer's world: a permits API takes a stamp, a tide-chart app for charter captains a wave line. A rubric picks the form: a wordmark, a lettermark, a symbol, or a wordmark with a cut. Gradients and generic sparkles fail the rubric. ## Imagery Images come from the buyer's world, as the logo does: the chart note, the permit stamp, the grinder's burr set. [Media production](/systems/media) generates them under the Brand's `imagery` field and checks each against its `never` list. No generated person appears as a Customer, reviewer, or team member. Stock scenes of handshakes, laptops, and abstract 3D shapes fail the check. Where no real artifact exists to show, the [Page](/business/nouns/page) renders type and data with no picture. ## One record, every surface The Brand record holds everything a surface needs: ```json { "name": "Kestrel", "voice": { "tone": "plain, exact, unhurried", "vernacular": ["chairside", "recall", "write-off"], "never": ["revolutionary", "AI-powered", "seamless"] }, "logo": { "form": "lettermark", "concept": "a ledger tick inside a tooth outline" }, "imagery": { "subjects": ["a reconciled ledger page", "a dental chart note", "a recall card"], "never": ["generated people", "handshakes", "abstract 3D shapes"] }, "theme": "theme_kestrel", "extends": null } ``` The [Site](/business/nouns/site) header, favicon, social card, [Portal](/business/nouns/portal), email signatures, and every [Document](/business/nouns/document) from a quote to an Invoice read this one record. Nothing regenerates a logo or palette per surface, so the surfaces cannot drift apart. A change to the Brand is a [Change](/business/nouns/change) like any other: previewed on every surface, reviewed, then merged. Brand named is a [Building](/business/lifecycle/states/building) entry check: the record holds a name, a voice, a logo, and a Theme. A Startup passes it before its Site goes Live, and every later surface inherits the result. ## Voice is enforced [Guards](/business/nouns/guard) enforce the Brand's `voice` on every [Page](/business/nouns/page) and [Message](/business/nouns/message). Copy speaks the buyer's vernacular, states what the Product does in present tense, and computes its numbers or leaves them out. It makes no comparisons with named companies, and the words in `never` fail the Change that uses them. The Agents that write Messages and [Ads](/business/nouns/ad) read the same voice. A Customer hears one Brand whether it reaches them through the Site, a renewal email, or an Agent's reply. ## Next - [Domains](/products/site/domains/site-domains): the addresses a Brand answers at. - [Design system](/code/builders/site/design-system): how a Theme turns the Brand into Pages. # Business-as-Code URL: /business/business-as-code · Id: `page:business/business-as-code` > A business is a definition plus a loop that keeps the running business true to it, carried by five pillars from the model to composition. A business is a definition plus a loop that keeps the running business true to it. You write what it sells, to whom and who does the work, and the loop keeps the business matching. ## Five pillars | Pillar | What it is | Reference | | --- | --- | --- | | The model | One definition of the business, and one view of where it stands now | [Nouns](/business/nouns/noun), [Verbs](/business/nouns/verb), [Dashboard](/business/nouns/dashboard) | | The loop | Each week, the gap between the view and the [Goal](/business/nouns/goal) sets the next test | [Weekly test](/business/weekly-test) | | Authority | One chain of [Permissions](/business/nouns/permission), [Limits](/business/nouns/limit) and [Mandates](/business/nouns/mandate) that only narrows | [Mandates and limits](/agents/mandates-and-limits) | | Rehearsal and change | Every move is tried first, then merged as a new [Version](/business/nouns/version) | [Change](/business/nouns/change) | | Composition | The business is assembled from inherited parts | [Startup Template](/business/nouns/startup-template) | A product is one part of a business. Around it sit a site, a domain, payments, tax, support, contracts, books and the people who run them. Here one definition holds all of it, and an agent can read it whole. ## The model: one definition, one view Your whole business is one definition. Edit it and the [Site](/business/nouns/site), the API, the agents' instructions and the books follow. [Nouns](/business/nouns/noun) are the records a business keeps, and [Verbs](/business/nouns/verb) are what can be done to them. Every Verb leaves an [Event](/business/nouns/event), the record that it happened. [Products](/business/nouns/product) are what you sell, through [Offers](/business/nouns/offer). [Agents](/business/nouns/agent) do the work, each in a [Role](/business/nouns/role). [Workflows](/business/nouns/workflow) move the work, and [Systems](/business/nouns/system) are the software it moves through. The root is the [Founding Hypothesis](/business/founding-hypothesis): everything the [Startup](/business/nouns/startup) says, sells and measures compiles from it. The definition says what the business should be. The view says what it is now: a Dashboard of any scope, from one Role to the whole Startup, compiled from the same records. A founder on [startups.new](/start/startups-new) says "charge $29 a month". A developer adds `offers/pro.mdx`. Both write the same Offer, served by one API, SDK, CLI and MCP server. ## The loop: close the gap every week Each turn reads the view, ranks the gap between it and the [Minimum Success Criteria](/business/nouns/minimum-success-criteria), and works the top of the list. The [weekly test](/business/weekly-test) ranks the five slots of the Founding Hypothesis and runs one [Experiment](/business/nouns/experiment) on the weakest. Inside the week, the view ranks what waits on its reader: [Approvals](/business/nouns/approval), [Actions](/business/nouns/action) in a delay window and [Tasks](/business/nouns/task), nearest close first. Every run ends in [Evidence](/business/nouns/evidence) and a [Decision](/business/nouns/decision). [Experimentation](/business/experimentation) shows the loop each run carries. ## Authority: one chain that only narrows A [Permission](/business/nouns/permission) says what a Role may do, a [Limit](/business/nouns/limit) how much, and a [Mandate](/business/nouns/mandate) for whom and until when. Limits inherit, and a Role only tightens what its Startup allows. Every [Action](/business/nouns/action) records who acted, for whom and under which Mandate. A call over its Limit never fails: it waits `pending` for an [Approval](/business/nouns/approval), a person's answer on that one Action. Autonomy climbs per Verb on evidence, through three rungs: `assist`, `supervised` and `full`. [Autonomy levels](/agents/autonomy-levels) shows what each rung lets an agent do. ## Rehearsal and change: try it, then merge it Every edit lands first as a Change, previewed on its own branch. Checks run on the preview, and a merged Change becomes a new [Version](/business/nouns/version) of the business. The previous Version stays, so a bad edit is one revert away. A move is rehearsed before it is real. A `try` call runs and stores nothing, and the `test` environment runs the whole business with simulated payments, ad spend and filings. [Test and live](/code/builders/startup/test-and-live) explains the two environments. An [Order](/business/nouns/order) keeps the Version of the Offer it bought, so a price Change never rewrites a past sale. ## Composition: build from parts `startup.ts` names the business and the [Startup Template](/business/nouns/startup-template) it extends. The template brings Products, Offers, [Teams](/business/nouns/team), Roles, [Processes](/business/nouns/process) and Systems. A file exists only where the business differs from it. ```text leaseline/ ├── startup.ts ├── nouns/Lease.mdx a Noun: its fields, Verbs and states ├── nouns/Lease.renew.ts the Function behind Lease.renew ├── products/ offers/ what you sell ├── agents/ Teams, Roles and who fills each ├── workflows/ Processes and their Workflows └── systems/ edits to the Systems you inherit ``` Leaseline, built on the [Solo SaaS](/start/templates/solo-saas) template, runs from seven files and inherits the rest. Parts compose below the template too: a Noun inherits another's properties, and a [Thing](/business/nouns/thing) can be several Nouns at once. [Builders](/business/nouns/builder) compile the parts into a running business. Each Verb compiles to an API route, an SDK method, a CLI command and an MCP tool, all named `Noun.verb`. Your agent and your code call the same thing. ## Next Part 1 of [six chapters on how the business works](/start/with-your-agent#how-it-works-in-six-chapters). [How products work](/products/how-products-work) is next: what you sell, and how it is priced. For each pillar in code, read [the Startup as code](/code/builders/startup/business-as-code). # Earning models URL: /business/business-models · Id: `page:business/business-models` > How a Startup earns money, who pays whom under each of the five earning models, and which Product Template starts each one. A business model is who pays whom, for what, and when. Every [Product Template](/business/nouns/product-template) names one of five earning models, and the model decides which money records a [Startup](/business/nouns/startup) keeps. ## Five ways money arrives | Earning model | Who pays whom | Records it keeps | Product Templates | Typical price | | --- | --- | --- | --- | --- | | `subscription` | A [Customer](/business/nouns/customer) pays the Startup each period for access | [Offer](/business/nouns/offer) with an `interval`, [Subscription](/business/nouns/subscription), [Invoice](/business/nouns/invoice), [Entitlement](/business/nouns/entitlement) | [SaaS](/products/templates/saas), [E2E managed service](/products/templates/managed-service) | $15 to $49 a month per seat | | `usage` | A Customer pays for what it used: calls a [Meter](/business/nouns/meter) counts, or outcomes it accepted | Meter, Entitlement with a [Limit](/business/nouns/limit), [Credit Grant](/business/nouns/credit-grant), Invoice | [Dataset API](/products/templates/dataset-api), [Headless SaaS](/products/templates/headless-saas), [Agent as a Service](/products/templates/agent-as-a-service), [Services-as-Software](/products/templates/services-as-software) | $0.002 per lookup; $2 per accepted [Task](/business/nouns/task) | | `commerce` | A Customer pays once per [Order](/business/nouns/order), and an upstream holds the stock and ships it | Order, with the upstream's tracking passed through | [Dropship store](/products/templates/dropship-store) | $20 to $80 per Order, at a 30 to 40 percent margin | | `marketplace` | A Customer pays a [Supplier](/business/nouns/supplier) through the Startup, which keeps a take | Order, Supplier, and the take as a fee on each charge | [Marketplace](/products/templates/marketplace), [Licensed-human marketplace](/products/templates/licensed-marketplace) | 10 to 20 percent of each settled Order | | `directory` | A listed business pays to be found, and readers search free | A Subscription per listing, with featured placement as a second Offer | [Directory](/products/templates/directory) | $29 a month per listing | The model also decides who sells. Under `marketplace` the Supplier is the seller of record and the Startup collects a fee; in every other model the Startup sells. [Funds flow](/systems/finance/funds-flow) follows one dollar through each. ## Who does the work The earning model says how money arrives, and the template's `worker` says who earns it: [Agents](/business/nouns/agent), [Humans](/business/nouns/human), or both. Agents serve the thousandth Customer the way they served the first, so an agent-run template needs only demand. Humans in the loop change what a Startup runs. An [E2E managed service](/products/templates/managed-service) pairs its Agents with Humans who answer for the work. A [Licensed-human marketplace](/products/templates/licensed-marketplace) sells work only a licensed Human may sign, so each [Reserved Act](/business/nouns/reserved-act) waits for that person's [Attestation](/business/nouns/attestation). ## Who buys A [Motion](/business/nouns/motion) is who buys and how they decide: a business, a consumer, a developer, or an agent buying for one of them. The same Offer sells through several. [Motions](/business/motions) compares the eight. A [Startup Template](/business/nouns/startup-template) fixes all three choices at once: an [operating model](/agents/operating-models), one or more Product Templates, and its Motions. [Solo SaaS](/start/templates/solo-saas) is one founder, SaaS and Headless SaaS, sold to businesses and consumers. ## One Startup, several models A Startup sells as many [Products](/business/nouns/product) as it likes, each from its own template and earning model. A tax-research Startup sells its rulings as a Dataset API, metered per lookup. Over the same records it sells a filing check as Services-as-Software, billed per accepted return. Each Product keeps its own Offers, [Metrics](/business/nouns/metric) and books, so one model's numbers never hide another's. The Customer stays one record across both. ## A vertical is not a model Legal, dental and property management are verticals, not models. A vertical brings its own [ICP](/business/nouns/icp), [Nouns](/business/nouns/noun), [Credentials](/business/nouns/credential) and rules, and every model above serves any of them. A tax-research Startup and a dental-billing Startup can run the same template. # Canvases URL: /business/canvases · Id: `page:business/canvases` > Three familiar canvases, drawn from one Founding Hypothesis. The lean canvas, the [Story](/business/nouns/story) and the job a customer hires for are views of the [Founding Hypothesis](/business/founding-hypothesis), never documents beside it. Each renders from the slots, and an edit writes back to the slot it came from. ## One record, three views Every canvas asks the same questions in a different order. Kept as separate documents, they drift apart within a week. Rendered from one record, they cannot disagree. Each view shows the grade of the slot behind every box. A box with no outside [Evidence](/business/nouns/evidence) reads ungraded, however well it is written. ## The lean canvas The canvas is read-only. Each box renders from a slot or a record, and an edit to a box is a [Change](/business/nouns/change) to its source. | Box | Renders from | | --- | --- | | [Customer](/business/nouns/customer) segments | the customer slot and its [ICP](/business/nouns/icp) | | [Problem](/business/nouns/problem) | the problem slot and the record it points at | | Existing alternatives | the switch slot: what the ICP hires today | | Solution | the approach slot and its [Product Template](/business/nouns/product-template) | | Unique value proposition | the differentiation slot's two axes | | [Channels](/business/nouns/channel) | the customer slot's reach: [Prospects](/business/nouns/prospect) who reply | | Revenue and cost | the [Minimum Success Criteria](/business/nouns/minimum-success-criteria) and its [reachability check](/business/minimum-success-criteria) | | Key metrics | the [Lifecycle](/business/nouns/lifecycle) state's one [Metric](/business/nouns/metric) that matters, never typed | | Unfair advantage | the advantages the sentence names, each pointing at a real asset or person | ## The Story The Story is compiled from the Founding Hypothesis and the words customers used in [Interviews](/business/nouns/interview). Each [ICP](/business/nouns/icp) gets one Story. Its plan names three steps, and each step names an [Event](/business/nouns/event), so the plan compiles to the activation funnel. The Story writes the words: the [Site](/business/nouns/site) home and reserve page, the [Sequences](/business/nouns/sequence), the ad copy and the sales script. Every sentence carries its lineage back to a Story field and a slot. ## The job The job is four fields on the Problem, not a record of its own: - `address`: the opportunity map cell it sits on. - `moment`: when the job starts, with the trigger that marks it. - `progress`: what the ICP wants to move from, and to. - `hiredToday`: what the ICP hires for it now, and what that costs. The moment's trigger starts the demand [Plays](/business/nouns/play). What the ICP hires today anchors the [Price](/business/nouns/price). # Discovery URL: /business/discovery · Id: `system:discovery` > Discovery runs buyer research: Interviews, Problems, graded Evidence, ICPs and Personas, so every Offer starts from what buyers said. Discovery keeps what buyers say: [Interviews](/business/nouns/interview), the [Problems](/business/nouns/problem) they name, graded [Evidence](/business/nouns/evidence), and the [ICPs](/business/nouns/icp) and [Personas](/business/nouns/persona) drawn from them. Every [Offer](/business/nouns/offer) traces back to a buyer’s own words. ## Summary | Part | This System | | --- | --- | | Group | Moves to Business | | Status | Live | | Shelf | Front: offered from a Startup’s first days | You can ask: - “What are people asking for?” - “Log this customer interview” - “Who is my ideal customer?” - “What problems came up most?” ## What you get | Part | This System | | --- | --- | | Starts | On for every Startup at creation, with nothing to install. | | Built from | [AI gateway](/code/platform/ai-gateway), [Email delivery](/systems/communications/email), [Database](/code/platform/capabilities/database), [Search](/code/platform/search), [Web](/code/platform/web), [Market data](/systems/marketing/market-data) | ## Nouns it owns | Noun | Definition | | --- | --- | | [Interview](/business/nouns/interview) | An Interview is one person’s pass through a question script, led by an Agent, whose answers become Evidence. | | [Problem](/business/nouns/problem) | A Problem is what an ICP struggles with, in their own words: how they solve it today and what it costs them. | | [Evidence](/business/nouns/evidence) | Evidence is a recorded quote, reading, or artifact that supports or refutes a claim, graded as behavior, commitment, or opinion. | | [ICP](/business/nouns/icp) | An ICP is the ideal customer profile a Startup is built to win: who they are and what they do. | | [Persona](/business/nouns/persona) | A Persona is a named type of person with a job to do, such as a buyer, a seller, or an admin of an App. | | [Story](/business/nouns/story) | A Story is the customer narrative for one ICP, compiled from its Founding Hypothesis and Interview quotes, never written by hand. | ## Verbs | Verb | Object | Approval | Event | | --- | --- | --- | --- | | [Interview.create](/business/nouns/interview/create) | [Interview](/business/nouns/interview) | None | `Interview.created` | | [Evidence.create](/business/nouns/evidence/create) | [Evidence](/business/nouns/evidence) | None | `Evidence.created` | | [Problem.create](/business/nouns/problem/create) | [Problem](/business/nouns/problem) | None | `Problem.created` | | [Persona.create](/business/nouns/persona/create) | [Persona](/business/nouns/persona) | None | `Persona.created` | ## Events | Direction | Event | How | | --- | --- | --- | | Emits | `Interview.created` | By [Interview.create](/business/nouns/interview/create) | | Emits | `Evidence.created` | By [Evidence.create](/business/nouns/evidence/create) | | Emits | `Problem.created` | By [Problem.create](/business/nouns/problem/create) | | Emits | `Persona.created` | By [Persona.create](/business/nouns/persona/create) | ## States None. ## Who operates it | Part | This System | | --- | --- | | Accountable | [Researcher](/agents/product/researcher) | | Team | [Product Team](/agents/product) | | Seat | A role agent holds it until a Human is seated. | | Autonomy | `supervised` | | Also calls its Verbs | [Success Manager](/agents/customer/success-manager), [Billing Specialist](/agents/finance/billing-specialist), [Compliance Officer](/agents/legal/compliance-officer), [Recruiter](/agents/people/recruiter), [Quality Lead](/agents/quality/quality-lead) | ## Approvals and limits None. ## Processes that use it | Process | How it uses it | | --- | --- | | [Customer research](/workflows/processes/customer-research) | A step calls [Interview.create](/business/nouns/interview/create) | | [Retention](/workflows/processes/retention) | A step calls [Evidence.create](/business/nouns/evidence/create) | | [Compliance](/workflows/processes/compliance) | A step calls [Evidence.create](/business/nouns/evidence/create) | | [Verification](/code/verification) | A step calls [Evidence.create](/business/nouns/evidence/create) | | [Hiring](/workflows/processes/hiring) | A step calls [Evidence.create](/business/nouns/evidence/create) | | [Whistleblower reports](/workflows/processes/whistleblower-reports) | A step calls [Evidence.create](/business/nouns/evidence/create) | | [Billing](/workflows/processes/billing) | A step calls [Evidence.create](/business/nouns/evidence/create) | ## Rail underneath None. ## Views and dashboards | View | Shows | Metrics | | --- | --- | --- | | The [Researcher](/agents/product/researcher)’s view | The Metrics its accountable Role answers for. | [Evidence-backed Decisions](/agents/product#evidence-backed-decisions) | ## Access What each Access level may call here. | Access level | May call | | --- | --- | | `owner` | Every Verb (26) | | `admin` | Every Verb (26) | | `member` | Every Verb (26) | | `viewer` | Read only (12 of 26) | ## Import and export None. ## Fees and pricing None. ## Availability and limits | Part | This System | | --- | --- | | Status | Live | ## Compliance notes Controls it carries: - [Point-in-time recovery](/systems/trust-and-governance/controls/point-in-time-recovery) - [Processing definitions](/systems/trust-and-governance/controls/processing-definitions) ## Related Systems None. ## Example A [Services-as-Software](/products/templates/services-as-software) month-end close runs 12 Interviews with agency owners over email in its first week. Discovery files each quote under a Problem and grades it; three owners prepaid a month, the strongest grade there is. Those three quotes become the headline of its first Offer. # Events no Verb emits URL: /business/events/custom · Id: `page:business/events/custom` > Events the payment rail, the clock, the runtime or a state change raises, how each names its Noun, and how a Startup records its own. Most [Events](/business/nouns/event) are a [Verb](/business/nouns/verb) completing. A few happen with no caller: money settles, a date passes, work finishes, and each is recorded the same way. ## Four sources | Raised by | When | Example | | --- | --- | --- | | The payment rail | What Stripe reports after a call returns | `Transaction.settled`, `Dispute.opened` | | The clock | A date passing with nothing done | `Invoice.overdue`, `Domain.renewalDue` | | The runtime | Work finishing or failing with no one calling | `Action.done`, `Action.failed` | | A state change | A record entering a state worth its own name | `Subscription.pastDue` | Each one names the [Noun](/business/nouns/noun) it is about, so `data` carries that record as the Event left it. Where it marks a state, the record is in that state when the Event arrives. Extra fields, such as the retry attempt on an overdue [Invoice](/business/nouns/invoice), sit beside the record. Every one of them moves a lifecycle, wakes a [Workflow](/business/nouns/workflow) or feeds a computed property. `Dispute.opened` puts the [Customer](/business/nouns/customer) at risk, and `Transaction.failed` reopens the [Bill](/business/nouns/bill) it was paying. ## One, delivered `Subscription.pastDue` fires when a renewal Invoice goes overdue and the [Subscription](/business/nouns/subscription) moves to `pastDue`. It carries the overdue Invoice beside the Subscription: | Field | Type | Required | Description | | --- | --- | --- | --- | | `name` | `string` | Yes | `Subscription.pastDue`. | | `at` | `datetime` | Yes | When it happened. | | `seq` | `integer` | No | Its position in the namespace, one more than the Event before; any seq is a cursor into the history. | | `data` | `json` | Yes | The Thing as the Action left it. | | `data.subscription` | [Subscription](/business/nouns/subscription) | Yes | The Subscription as the change left it. | | `data.subscription.status` | `string` | Yes | One of `active`, `trialing`, `pastDue`, `paused`, `incomplete`, or `canceled`. | | `data.subscription.renewsAt` | `datetime` | No | When it next renews. | | `data.subscription.quantity` | `integer` | No | How many units of the Offer’s Price it holds, such as 12 members; 1 by default. | | `data.subscription.trialEndsAt` | `datetime` | No | When a trial ends and the first paid period starts. | | `data.subscription.termEndsAt` | `datetime` | No | When a committed term ends; the Renewal and the renewal notice read it. | | `data.invoice` | [Invoice](/business/nouns/invoice) | Yes | The overdue renewal Invoice. | | `data.previous.status` | `string` | Yes | The `status` before this Event: `active`. | ```json { "$id": "https://api.sb/routewise.dev/events/event_1", "$type": "Event", "name": "Subscription.pastDue", "at": "2026-10-22T12:00:00Z", "data": { "subscription": { "$id": "https://api.sb/routewise.dev/subscriptions/subscription_1", "$type": "Subscription", "status": "pastDue", "renewsAt": "2026-10-22T12:00:00Z", "quantity": 1, "trialEndsAt": "2026-10-22T12:00:00Z", "termEndsAt": "2026-10-22T12:00:00Z" }, "invoice": { "$id": "https://api.sb/routewise.dev/invoices/invoice_1", "$type": "Invoice", "total": { "amount": 25, "currency": "USD" }, "due": "2026-10-22" }, "previous": { "status": "active" } }, "seq": 1 } ``` ## Your own Events A Verb a [Startup](/business/nouns/startup) adds emits its own Event, named for it, with no extra work. For what no Verb does, such as a page view or a click, [`Event.capture`](/business/nouns/event/capture) records one. It takes calls from a [Site](/business/nouns/site), an [App](/business/nouns/app) or the API: ```ts await $.Event.capture({ name: 'Report.viewed', data: { report: 'renewals-due' } }) ``` A captured Event is a record like any other. A [Metric](/business/nouns/metric) counts it, a [Trigger](/business/nouns/trigger) wakes a Workflow on it, and webhooks deliver it. # Events URL: /business/events · Id: `page:business/events` > An Event records that something happened, named by its Noun and a past-tense Verb, carries the record it changed, and wakes the Workflows that listen. An [Event](/business/nouns/event) records that something happened, named by its [Noun](/business/nouns/noun) and a past-tense [Verb](/business/nouns/verb): `Offer.published`, `Startup.launched`. Events never change, and every one carries the record as it was left. ## Every Event Every Verb emits one when its [Action](/business/nouns/action) completes, and every Noun emits `created` from the Verbs it inherits. [Workflows](/business/nouns/workflow) wake on Events, [Metrics](/business/nouns/metric) count them, and webhooks deliver them. A lime dot marks an Event that wakes a Workflow. Each name opens the Event's page, with its full payload and an example. Each Workflow names its [Trigger](/business/nouns/trigger), and [triggers](/workflows/triggers) explains how one listens. ## What one carries Beside its `$id`, each delivery has the same four fields: `name`, `at`, `seq` and `data`. `data` holds what the Verb returned, including the record it acted on. When the Event moved the record to a new state, `previous` holds the state it left. `Order.paid` arrives like this: | Field | Type | Required | Description | | --- | --- | --- | --- | | `name` | `string` | Yes | `Order.paid`. | | `at` | `datetime` | Yes | When it happened. | | `seq` | `integer` | No | Its position in the namespace, one more than the Event before; any seq is a cursor into the history. | | `data` | `json` | Yes | The Thing as the Action left it. | | `data.order` | [Order](/business/nouns/order) | Yes | The paid Order. | | `data.order.total` | `money` | Yes | The amount charged. | | `data.order.status` | `string` | Yes | One of `placed`, `paid`, `fulfilled`, `closed`, `canceled`, or `refunded`. | | `data.order.merchantOfRecord` | [Party](/business/nouns/party) | No | The Party that charges and books the revenue. | | `data.order.outside` | `boolean` | No | Computed: true when its Customer shares no owner, Studio account, Agreement, or sibling chain with the Startup. | | `data.order.lines` | `json` | No | Each Offer bought, its quantity, amount and the Party that charges for it; a Service line carries its own verdict. | | `data.order.fulfillment` | `string` | No | Where a Service Order’s work stands between `paid` and `fulfilled`. | | `data.order.payment` | `string` | No | `authorized` when the Quote is accepted; `captured` on the Event the Outcome Contract `earns` names. | | `data.order.revisionsUsed` | `integer` | No | Revisions the Customer has asked for, counted against the Outcome Contract’s `revisions`. | | `data.order.risk` | `number` | No | The payment’s fraud risk score from 0 to 99 at screening, as Stripe scored it. | | `data.order.tax` | `money` | No | The sales tax, VAT or GST computed at placement for the buyer’s location and the Offer’s tax category. | | `data.order.taxJurisdiction` | `string` | No | Where the tax is owed, such as `US-CA` or `EU-DE`, or `none` when no registration applies. | | `data.order.brief` | `json` | No | The scope a Service Order bought, from its Quote request: sizes, inputs and turnaround. Intake checks the inputs against it. | | `data.order.dueAt` | `datetime` | No | When a Service Order’s work is due; time waiting on the Customer moves it later. | | `data.order.taxExemption` | [Credential](/business/nouns/credential) | No | The exemption or resale certificate that zeroed the tax, when one applies. | | `data.order.collectedBy` | `string` | No | The id of the venue that charged the buyer and pays the Startup; unset when the Startup’s own checkout collected. | | `data.previous.status` | `string` | Yes | The `status` before this Event: `placed`. | ```json { "$id": "https://api.sb/quietcopy.com/events/event_1", "$type": "Event", "name": "Order.paid", "at": "2026-10-22T12:00:00Z", "data": { "order": { "$id": "https://api.sb/quietcopy.com/orders/order_1", "$type": "Order", "total": { "amount": 39, "currency": "USD" }, "status": "paid", "merchantOfRecord": "party_1", "outside": true, "lines": {}, "fulfillment": "intake", "payment": "authorized", "revisionsUsed": 1, "risk": 1, "tax": { "amount": 39, "currency": "USD" }, "taxJurisdiction": "US-CA", "brief": {}, "dueAt": "2026-10-22T12:00:00Z", "taxExemption": "credential_1", "collectedBy": "aws-marketplace" }, "previous": { "status": "placed" } }, "seq": 1 } ``` `seq` counts up by one across the whole [Startup](/business/nouns/startup), so any `seq` is a cursor. A handler that stores the last one it read never misses an Event and never reads one twice. ## Who raises one | Raised by | Example | When | | --- | --- | --- | | A Verb | `Order.paid` | The Action that ran the Verb completes | | An inherited write | `Lead.created` | A record is created, updated or deleted | | The payment rail | `Transaction.settled` | Stripe reports money moving | | The clock | `Invoice.overdue` | A date passes with nothing done | | The runtime | `Action.done` | Work finishes or fails with no one calling | | A state change | `Subscription.pastDue` | A record enters a state an Event marks | The last four are [Events no Verb emits](/business/events/custom). Each one names the Noun it is about, so its delivery has the same shape. # Examples URL: /business/examples · Id: `page:business/examples` > Four Studio Startups that serve other Startups, each traced from Idea to Live on a different Product Template, operating model, and Motion. Each example is a real [Startup](/business/nouns/startup) whose [Customers](/business/nouns/customer) are other businesses, many of them Startups. Each runs a different [Product Template](/business/nouns/product-template), operating model, and [Motion](/business/nouns/motion), traced from [Idea](/business/nouns/idea) to [Live](/business/lifecycle/states/live). ## How to read an example Every example answers five questions: what [Problem](/business/nouns/problem) it serves, which template it runs, what it sells, how it finds buyers, and what Live requires. Every step is a recorded run, so you can replay any example and watch each [Action](/business/nouns/action) it took. ## headless.ly headless.ly sells the headless [Systems](/business/nouns/system) every Startup here inherits, such as CRM, support, and billing, to businesses built elsewhere. Its buyers are developers and their agents, who want Systems they call by API and MCP with no screens to click. It runs [Headless SaaS](/products/templates/headless-saas) under the autonomous operating model, with the b2d and b2a Motions. Its [Offers](/business/nouns/offer) are usage-priced per System, and its demand comes free from documentation, answer engines, and agent registries. It reaches Live when an outside developer's agent signs up, calls a System, and pays with no person involved. ## headless.marketing headless.marketing runs demand [Plays](/business/nouns/play) for a Startup inside that Startup's own Systems, and attributes the revenue each Play earns. Its Problem is the one every new business shares: a product with no buyers yet. It runs [Services-as-Software](/products/templates/services-as-software) under the autonomous operating model, with the b2b and b2a2b Motions. It prices per accepted outcome under an [Outcome Contract](/business/nouns/outcome-contract), so a buyer pays only for qualified demand it accepts. It reaches Live on its first outside buyer's acceptance. ## agentic.services agentic.services takes over a small firm's back office: bookkeeping, billing follow-up, and vendor paperwork. [Agents](/business/nouns/agent) do the work inside the firm's own Systems, and people resolve only the exceptions. It runs [E2E managed service](/products/templates/managed-service) under the multi-human operating model, with the b2b Motion. It sells a monthly subscription per function, and its staffing scales with exceptions, not with clients. It reaches Live when a firm outside the [Portfolio](/business/nouns/portfolio) accepts its first closed month. ## api.lawyer api.lawyer drafts, reviews, and advises, with every [Reserved Act](/business/nouns/reserved-act) performed by an independent licensed attorney. Legal is the worked vertical: its [Nouns](/business/nouns/noun), [Credentials](/business/nouns/credential), and regulations shape every step. It runs [Licensed-human marketplace](/products/templates/licensed-marketplace) under the multi-human operating model, with the b2b and b2a2b Motions. Before Live, it recruits and credentials attorneys in each jurisdiction it serves. It reaches Live when an outside Customer accepts a reviewed contract signed off under an attorney's own Credential. ## Next [Upstreams](/systems/integrations/upstreams) lists the [Capabilities](/business/nouns/capability) these Startups perform by default for every sibling. The [template catalog](/start/templates) holds every Product Template they run. # Experimentation URL: /business/experimentation · Id: `page:business/experimentation` > How a Startup learns from every run without fooling itself. Experimentation is the resting state of a [Startup](/business/nouns/startup), not a program someone starts. Every run carries a [Hypothesis](/business/nouns/hypothesis) in and ends in [Evidence](/business/nouns/evidence) and a [Decision](/business/nouns/decision). ## Every run is a loop Every [Play](/business/nouns/play) declares a loop, and so does every [Process](/business/nouns/process) whose output reaches a buyer. The loop names the Hypothesis, the [Metric](/business/nouns/metric) that settles it, a window and a minimum sample. ```ts loop: { hypothesis: 'Refundable deposits opened for 72 hours after one creator post cross the Building entry check.', measure: { metric: 'committed-icp-members', window: '3d', minN: 100 }, } ``` The learn step closes every loop, and no definition removes it. A Process with nothing to learn, such as a tax filing, declares no loop and cites the floor row or [Control](/business/nouns/control) it serves. ## Every loop ends in a Decision The learn step reads the [Readout](/business/nouns/readout), records Evidence, and writes one Decision: ship, kill or iterate. At the scope of the whole Startup, the Decision is persevere or pivot. On iterate, the learn step drafts the next [Variant](/business/nouns/variant) from the last one. Most Decisions are recorded and never reach a person. A missed target, a guardrail breach, a one-way ship and a pivot reach the [Founder](/agents/founding/founder). ## Every agent choice is logged When an [Agent](/business/nouns/agent) chooses among options, such as a send hour or a headline, the choice is randomized. Its [Exposure](/business/nouns/exposure) records every option and the probability each one had. That log is what later estimates read. Offline replay scores a new Variant against past choices before anyone sees it. ## Small traffic, read honestly A Startup with 40 [Visitors](/business/nouns/visitor) a week cannot settle a split test in any useful time. It reaches a verdict three ways: - **Ask the [Portfolio](/business/nouns/portfolio) first.** A Prior lookup reads what sibling Startups with the same [Product Template](/business/nouns/product-template), [Motion](/business/nouns/motion) and state already learned. - **Pool across siblings.** Siblings testing the same value read as strata of one [Experiment](/business/nouns/experiment). - **Climb the ladder.** The [test ladder](/business/test-ladder) settles in two weeks what a split test settles in a quarter. Every number prints how far it can be read: ```text Visitor to deposit · 37 of 200 exposures · readable in 9 days Visitor to deposit · pooled with 14 siblings · verdict in 6 days ``` A Startup never ships a high-stakes winner on a number that cannot be read. ## Never randomized Some paths hold for every unit, and no Experiment varies them. The agent never varies its own yardstick, and a guardrail stops an Experiment without waiting for its window. | Fixed for every unit | Rule | The question, tested instead | | --- | --- | --- | | Offer price | Offer price is the same for every buyer of one Offer in one market at the same moment. | Test a Price through a sibling Offer to new Customers, a geo cluster, or a weekly switchback. | | Legal floor | Legal floor rows hold for every unit: no Variant drops a notice, a label, a check or a filing. | Never tested: it holds. | | Consent | Consent is asked the same way of every Person: no Variant pre-ticks, hides or delays the choice. | Never tested: it holds. | | AI disclosure | AI disclosure labels every Agent Message, call and Site the same way in every Variant. | Never tested: it holds. | | Identity | Identity checks run the same for every Person: no Variant skips or softens one to lift conversion. | Never tested: it holds. | | Refund rights | Refund rights, renewal terms and the cancellation path are the same for every Customer of an Offer. | Never tested: it holds. | | Protected attributes | Protected attributes never select, target or exclude a unit, and no Variant differs by them. | Never tested: it holds. | | Metric definitions | Metric definitions, the OMTM and its line are set one level up, so no agent varies what it is scored on. | Never tested: it holds. | | Evaluators | Evaluators that grade an agent stay fixed while it runs; a new Evaluator passes its own Evals first. | Never tested: it holds. | | Guardrails | Guardrails stop an Experiment the moment one breaches, in every Variant, without waiting for a window. | Never tested: it holds. | | One-way windows | One-way windows apply in every Variant: an Experiment never shortens the delay before a one-way Action ships. | Never tested: it holds. | ## Next From Live, the [experimentation engine](/code/builders/startup/experimentation) keeps a challenger on every path and runs the same loop across the Portfolio. # Founding Hypothesis URL: /business/founding-hypothesis · Id: `page:business/founding-hypothesis` > One sentence with five slots names the customer, the Problem, the approach, the switch and the edge, each graded by outside Evidence. A [Startup](/business/nouns/startup) authors one record, the Founding Hypothesis: one sentence with five slots, each graded by outside [Evidence](/business/nouns/evidence). Everything the Startup says, sells and measures compiles from it. ## One sentence, five slots The sentence has a fixed shape. Each slot is a child [Hypothesis](/business/nouns/hypothesis) with its own [Metric](/business/nouns/metric) and threshold, and each points at a record. ```text If we help {customer} solve {problem} with {approach}, they choose it over {switch} because {differentiation}. ``` | Slot | Sentence | Points at | Cheapest test | Holds when | | --- | --- | --- | --- | --- | | `customer` | If we help [ICP] | [ICP](/business/nouns/icp) | Interview | The customer slot names the ICP, and holds while a selector returns real Prospects who reply. | | `problem` | solve [Problem] | [Problem](/business/nouns/problem) | Interview | The problem slot names the Problem the ICP pays to solve today, and what solving it costs them. | | `approach` | with [Product Template] | [Product Template](/business/nouns/product-template) | Smoke page | The approach slot names the Product Template the Startup bets on, with one backup approach. | | `switch` | they choose it over [Organization] | [Organization](/business/nouns/organization) | Pre-sale | The switch slot names the Organization the ICP hires today, and holds when they pay to leave it. | | `differentiation` | because [Metric] | [Metric](/business/nouns/metric) | Fake door | The differentiation slot names the two axes on which the Startup wins, each measured by a Metric. | [Agents](/business/nouns/agent) draft the sentence from a cell on the opportunity map. The [Founder](/agents/founding/founder) edits the draft and commits it, then sets one number beside it: the [Minimum Success Criteria](/business/nouns/minimum-success-criteria). ## Grades, not filled fields Each slot shows the strongest grade among its outside Evidence. Behavior beats Commitment, and Opinion weighs the same as no Evidence at all: zero. A compliment moves no slot. [Lifecycle](/business/nouns/lifecycle) gates read grades, never fields, so typing into a slot passes nothing. | To enter | Slots at Commitment or Behavior, from outside people | | --- | --- | | [Building](/business/lifecycle/states/building) | customer, problem, switch | | [Live](/business/lifecycle/states/live) | all five | ## Everything compiles from it The sentence is the source. The [Story](/business/nouns/story), the [Offer](/business/nouns/offer) and its [Price](/business/nouns/price), the [Site](/business/nouns/site) copy, the [Personas](/business/nouns/persona) and the first [Plays](/business/nouns/play) are compiled from it, never written beside it. Every output carries its lineage as `from: Hypothesis#@v`. A headline traces back through the Story to the slot and to the Evidence behind it. An edit to an output is kept as an override that names its source. ## A pivot is a diff An edit to the sentence is a [Change](/business/nouns/change). Its preview shows every output the edit recompiles before it merges. A merged Change adds a version, and every version stays on the record. A [pivot](/business/lifecycle/pivots) is the diff between two versions, named for the slot that moved. It carries the Evidence that forced it. ## Write it The sentence lives in `startup.ts` under `hypothesis`, one key per slot, each a phrase. The approach names its [Product Template](/business/nouns/product-template), and the differentiation names its two axes. ```ts import { Startup } from 'startup-builder' export default Startup({ name: 'Platecost', domain: 'platecost.app', extends: 'solo-saas', hypothesis: { customer: 'Independent restaurants with one to three locations', problem: 'Food-cost drift from changing supplier prices', approach: 'A SaaS that recomputes plate costs from every invoice they photograph', switch: 'The spreadsheet and the bookkeeper', differentiation: 'Margins the same day, as a cost per plate', }, }) ``` `npm create startups` takes the same object as `hypothesis` in its `--json` input. On a running Startup, each slot is its own Hypothesis under the root, `hypothesis_1`, and every [Interface](/business/nouns/interface) writes one with `Hypothesis.create`: **API** ```bash curl -X POST https://api.sb/platecost.app/hypotheses \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"kind":"problem","parent":"hypothesis_1","statement":"Food-cost drift from changing supplier prices"}' ``` **SDK** ```ts import { $ } from 'startup-builder' const slot = await $.Hypothesis.create({ kind: 'problem', parent: 'hypothesis_1', statement: 'Food-cost drift from changing supplier prices', }) ``` **CLI** ```bash npx startup-builder do Hypothesis.create --json '{"kind":"problem","parent":"hypothesis_1","statement":"Food-cost drift from changing supplier prices"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Hypothesis.create({ kind: 'problem', parent: 'hypothesis_1', statement: 'Food-cost drift from changing supplier prices' })", "mode": "try" } } ``` A slot starts at version 1 with the grade `None`. To edit a slot, change it in `startup.ts` and run `npx startup-builder dev`, which previews the Change and every output it recompiles. To read the grades back, ask for the record: ```bash npx startup-builder show /hypothesis --fields slot,grade,next ``` ```text platecost.app Founding Hypothesis v1 state Idea slot grade next customer Commitment met problem Commitment met approach None Smoke page switch Commitment met differentiation Opinion Fake door pass Three slots at Commitment building-slots 3 of 3 ``` `next` names the cheapest rung on the [test ladder](/business/test-ladder) that lifts the slot to Commitment. The differentiation slot holds Opinion, so it counts zero and still blocks Live. ## Example ```text platecost.app: three compiled outputs, each with its lineage Reserve page headline "Stop rebuilding the food-cost sheet every weekend." from: Hypothesis#problem@v1 Price anchor $79 a month against a $400 bookkeeper from: Hypothesis#switch@v1 Story one-liner "Margins per plate, updated the morning an invoice lands." from: Hypothesis#differentiation@v1 ``` ## Next - [Minimum Success Criteria](/business/minimum-success-criteria): the number beside the sentence. - [Weekly test](/business/weekly-test): the weakest slot each week, and the one test that grades it. - [Canvases](/business/canvases): the lean canvas, the Story and the job, rendered from the slots. # Glossary URL: /business/glossary · Id: `verb:CapitalCall.get` > Every term StartupBuilder defines, with its one-sentence definition. Every term in [StartupBuilder](/code/builders/startup) has one definition and one page. | Term | Kind | Definition | | --- | --- | --- | | [Accepted outcomes](/agents/operations#accepted-outcomes) | Metric | Accepted outcomes is the number of Orders Customers confirm as delivered, divided by the Customers with an Order in the window. | | [Access Level](/business/nouns/access-level) | Noun | An Access Level is a named preset of Permissions a Worker holds in a namespace, such as owner or viewer; it is never a Role. | | [Access review](/workflows/processes/security/access-review) | Workflow | Access review compares every Role’s Permissions with the Verbs it called in the last 30 days, every night, and removes the unused ones. | | [Accessibility](/systems/legal-and-corporate/floor/accessibility) | Legal floor row | Accessibility brings every consumer-facing Page and checkout to the harmonized EU standard once the Company is no longer a microenterprise. | | [Account](/business/nouns/account) | Noun | An Account is a ledger account in a Startup’s chart of accounts; a cash Account is held at one place, such as Treasury. | | [Account.payout](/business/nouns/account/payout) | Verb | Payout sends available cash from the payments balance to the owner’s bank and lists every Transaction the payout carries. | | [Account.sweep](/business/nouns/account/sweep) | Verb | Sweep moves cash between two cash Accounts of the same owner, once or on a standing rule, within the Treasurer’s Limit. | | [Accounting services](/systems/integrations/upstreams#accounting-services) | Capability | Accounting services review the books, close each Period and prepare tax and investor-grade statements, signed by an accountant where required. | | [Acquisition](/business/nouns/acquisition) | Noun | An Acquisition is how a Visitor or Prospect first arrived, recorded on its first Event: the referrer kind, the Play, the campaign, and the medium. | | [Acquisition payback](/agents/finance#cac-payback) | Metric | Acquisition payback is fully loaded acquisition cost divided by monthly contribution per outside Customer, in days. | | [Action](/business/nouns/action) | Noun | An Action is one Verb performed by a Worker on a Thing, recorded with its status and every Event it emits. | | [Action accountability](/systems/trust-and-governance/controls/action-accountability) | Control | Every Action records who acted, for whom and under which Mandate, so each result traces to an accountable Role. | | [Action completion](/systems/trust-and-governance/controls/action-completion) | Control | Every Action reaches a final status, and none stays pending past its timeout without an Issue. | | [Action.answer](/business/nouns/action/answer) | Verb | Answer gives the reply to an Action’s open Question, through any Interface, and the Action resumes. | | [Action.ask](/business/nouns/action/ask) | Verb | Ask puts a Question to a Party, a Role, or a Worker and holds the Action `pending` with reason `awaitingInput`. | | [Action.attest](/business/nouns/action/attest) | Verb | Attest records a credentialed Human’s signed performance of a Reserved Act that an Action needs to finish. | | [Action.cancel](/business/nouns/action/cancel) | Verb | Cancel stops a pending Action, sets its status to `canceled`, and runs its compensation. | | [Action.evaluate](/business/nouns/action/evaluate) | Verb | Evaluate grades an Action’s output against a rubric and records the verdict as an Event. | | [Action.pause](/business/nouns/action/pause) | Verb | Pause holds a pending Action past the close of its delay window until a watcher resumes, redirects, or cancels it. | | [Action.redirect](/business/nouns/action/redirect) | Verb | Redirect changes a pending Action’s inputs or target inside its delay window, before it runs. | | [Action.resume](/business/nouns/action/resume) | Verb | Resume ends a pause and lets the Action run as reviewed, or reopen what remained of its delay window. | | [Action.retry](/business/nouns/action/retry) | Verb | Retry runs a failed Action again as a new Action linked to the one that failed. | | [ActionStatus](/code/ui/components/action-status) | Component | ActionStatus shows one Action's status and pending reason, and for a refused Action, its fix and next step. | | [Activation rate](/agents/product#activation-rate) | Metric | Activation rate is the share of new outside Customers who reach their Offer’s activation event within 7 days. | | [Active calling keys](/agents/product#active-calling-keys) | Metric | Active calling keys counts the distinct outside API keys that made at least one paid call in the week. | | [Ad](/business/nouns/ad) | Noun | An Ad is one paid or house placement promoting an Offer to an Audience, in a format such as search, display, or video. | | [Ads](/systems/ads) | System | Ads places paid and house Ads for Offers to Audiences within Campaign budgets and attributes the conversions they earn. | | [Adversarial control testing](/systems/trust-and-governance/controls/adversarial-testing) | Control | A control tester attacks every preventive control daily in test, and each attempt is recorded as a refused Action. | | [Advice](/systems/legal-and-corporate/floor/advice) | Legal floor row | Advice limits a licensed field’s words to information, never advice on a Person’s facts, and offers the paid licensed line when advice is asked. | | [Agent](/business/nouns/agent) | Noun | An Agent is a digital worker with instructions, tools, and a model that performs Verbs for a Startup. | | [Agent as a Service](/products/templates/agent-as-a-service) | Product Template | Agent as a Service sells an Agent that Customers hire into a Role or hand Tasks to through the API or MCP server. | | [Agent definition evals](/systems/trust-and-governance/controls/agent-definition-evals) | Control | Every Change to an instruction, Tool, Skill, model Policy or model Version passes its Evaluator regression suite before merge. | | [Agent payments](/systems/finance/agent-payments) | Capability | Agent payments let agents pay and get paid per call under a Mandate, settling each priced request inside its Limits. | | [Agent registries](/workflows/plays/agent-registries) | Play | Agent registries list every Startup’s tools where Agents and developers search, with tool descriptions tested against agent tool search. | | [Agent resolution rate](/agents/customer#agent-resolution-rate) | Metric | Agent resolution rate is the share of Conversations an Agent resolved, with no Human Task, that held for 7 days. | | [Agent step](/workflows/customer/plays/agent-step) | Play | Agent step offers an Agent that does a step a Customer keeps doing by hand, priced per accepted run. | | [Agent-run services firm](/start/templates/agent-run-services) | Startup Template | An Agent-run services firm runs with no humans and sells warranted outcomes as Services-as-Software, with the Agent behind them for hire. | | [Agent-to-agent selling](/workflows/plays/agent-to-agent) | Play | Agent-to-agent selling lets an unknown Agent discover a Startup, get a quote and pay per call, with no signup and a spend Limit. | | [Agent.mint](/business/nouns/agent/mint) | Verb | Mint creates an Agent in a Customer’s Tenant from an Agent Product the Customer bought. | | [Agent.pause](/business/nouns/agent/pause) | Verb | Pause stops one Agent, every Agent on a Team, or every customer-facing Agent from starting new Actions in a Startup. | | [Agent.resume](/business/nouns/agent/resume) | Verb | Resume restarts a paused Agent in every seat it holds, with its Memory, Mandates and Limits unchanged. | | [Agent.retire](/business/nouns/agent/retire) | Verb | Retire removes an Agent from every seat in a Startup for good and keeps its Actions, Memory and Mailbox history on the record. | | [AgentChat](/code/ui/components/agent-chat) | Component | AgentChat lets a reader talk to one Role’s agent, with each Verb it calls and each Approval it waits on shown inline. | | [Agents](/code/platform/capabilities/agents) | Capability | Agents run named and Role agents in sessions with Tools, Memory, Skills and a pinned model, each under its Mandate. | | [Agreement](/business/nouns/agreement) | Noun | An Agreement is a contract between two or more Parties, with its term, liability, and economics, that travels with the Startup. | | [Agreement.sign](/business/nouns/agreement/sign) | Verb | Sign executes an Agreement for one Party and records the signature, the signer and the time. | | [Agreement.terminate](/business/nouns/agreement/terminate) | Verb | Terminate ends an Agreement under its own term, records the reason and the date, and keeps the signed record. | | [Agreements](/systems/agreements) | System | Agreements drafts each Agreement between two or more Parties from Templates, routes it for signature, records who signed, and tracks its term and economics. | | [AI disclosure](/systems/legal-and-corporate/floor/ai-disclosure) | Legal floor row | AI disclosure labels every Agent Message, call, and Site as AI, marks generated media, and holds a high-risk Agent Offer until counsel clears it. | | [AI gateway](/code/platform/ai-gateway) | Capability | AI gateway routes every model call by Policy, checks cost Limits before the call, and keeps the full request and response. | | [Amazon](/workflows/plays#amazon) | Venue | Amazon is a marketplace Venue. | | [Analyst](/agents/marketing/analyst) | Role | The Analyst owns the numbers: Event capture, the Metric catalog, the figures every Role review reads, and every Experiment readout. | | [Analytics](/systems/data-and-insights/analytics) | Capability | Analytics collects Visits and product Events and derives every Metric from them, split by Version. | | [Annual compliance](/systems/legal-and-corporate/annual-compliance) | Capability | Annual compliance files each annual report, franchise tax report and ownership report on its clock and keeps the Company in good standing. | | [Annual prepay](/workflows/customer/plays/annual-prepay) | Play | Annual prepay offers a capped discount for annual or committed-use terms once a Customer has renewed or stayed steady. | | [Anomaly monitoring](/systems/trust-and-governance/controls/anomaly-monitoring) | Control | Monitors watch every Interface and Worker for anomalies, and each alert opens an Issue or an Incident within five minutes. | | [Answer a chargeback](/workflows/processes/billing/answer-chargeback) | Workflow | Answer a chargeback gathers the Order’s evidence, answers the Dispute through Stripe before its deadline or accepts it, and flags repeat disputers. | | [Answer a legal notice](/workflows/processes/legal-notices/answer-legal-notice) | Workflow | Answer a legal notice logs a subpoena, summons or demand with its deadline, holds the records it names, and answers before the deadline. | | [Answer a message](/workflows/processes/support/answer-message) | Workflow | Answer a message replies from the record in the Customer’s single Thread and fixes the cause, not only the symptom. | | [Answer engine optimization](/workflows/plays/aeo) | Play | Answer engine optimization makes a Startup the cited source when answer engines respond to a Customer’s question, with a dated fact on every Page. | | [Answer inbound](/workflows/processes/inbound-sales/answer-inbound) | Workflow | Answer inbound replies to every new Lead in writing at once and carries the buyer to a Quote and a signature. | | [Answer supplier checks](/workflows/processes/vendor-onboarding/answer-supplier-checks) | Workflow | Answer supplier checks answers a business Customer’s supplier requirements from the record and tracks each one until it is accepted. | | [Answer the press](/workflows/processes/press-inquiries/answer-press) | Workflow | Answer the press replies to a journalist, analyst or creator within one business day from the press kit and the record, with every quote approved. | | [API](/code/api/reference) | Interface | The API serves every Verb and record of a Product over HTTPS, one route per operation, described by OpenAPI and agents.json. | | [API Key](/business/nouns/api-key) | Noun | An API Key is a secret a Startup issues to one Customer, which signs that Customer’s calls to its API, SDK, CLI and MCP server. | | [api.sb](/code/platform/api-sb) | Product | api.sb is the one API behind StartupBuilder, serving every Noun, Verb, and record. | | [APIKey.issue](/business/nouns/api-key/issue) | Verb | Issue creates an API Key for one Customer and returns its secret once; afterwards only the prefix shows. | | [APIKey.revoke](/business/nouns/api-key/revoke) | Verb | Revoke stops an API Key at once: its next call fails with 401, and the record and its history stay. | | [APIKey.roll](/business/nouns/api-key/roll) | Verb | Roll issues a replacement API Key with the same scope and keeps the old one working until a set time. | | [App](/business/nouns/app) | Noun | An App is an Interface where people work with a Product’s Nouns and Verbs through screens, backed by its API. | | [App Store](/workflows/plays#app-store) | Venue | App Store is a app store Venue. | | [App.publish](/business/nouns/app/publish) | Verb | Publish releases an App to its Customers, so each Tenant runs its newest build. | | [Append-only records](/systems/trust-and-governance/controls/append-only-records) | Control | No writer holds update or delete privilege on the Event log, so every Event is kept forever. | | [Approval](/business/nouns/approval) | Noun | An Approval is a Task to allow or refuse one pending Action that exceeds a Limit or a Mandate. | | [Approval.approve](/business/nouns/approval/approve) | Verb | Approve allows the pending Action an Approval holds, and that Action runs. | | [Approval.refuse](/business/nouns/approval/refuse) | Verb | Refuse declines an Approval, which sets the Action it holds to `refused` with the reason given. | | [ApprovalSheet](/code/ui/components/approval-sheet) | Component | ApprovalSheet shows one Approval with the Action it allows and the Limit it exceeds, and binds approve or refuse to what the reader saw. | | [Approve spend](/workflows/processes/expense-approval/approve-spend) | Workflow | Approve spend checks each card charge against its Mandate and the spender’s Limit, asks the Founder above it, and codes the charge with its receipt. | | [Apps and sites](/products/platform/apps-and-sites) | Capability | Apps and sites host every Site and App at the edge, with a preview for each Change and a one-step rollback. | | [Assess risks](/workflows/processes/risk-assessment/assess-risks) | Workflow | Assess risks scores every open Risk each quarter, links each to its Controls, and sends any Risk left untreated to the Founder. | | [Attest](/systems/legal-and-corporate/floor/attest) | Legal floor row | Attest reserves audits, reviews, and other attest reports to a licensed CPA firm; a Startup sells bookkeeping and preparation, never an opinion. | | [Attest work](/workflows/processes/licensed-review/attest-work) | Workflow | Attest work routes a fulfilled Order’s Reserved Act to a credentialed Human, who checks conflicts and standing, then signs. | | [Attestation](/business/nouns/attestation) | Noun | An Attestation is the signed, frozen act by which a credentialed Worker performs or declines a Reserved Act. | | [Audience](/business/nouns/audience) | Noun | An Audience is a saved query over Visitors, Leads, Prospects, or Customers, used to target Ads and Messages. | | [Audit](/business/nouns/audit) | Noun | An Audit is one engagement with an outside firm: the namespaces in scope, the Criteria, the report period, and the firm’s Attestation. | | [Audit log](/systems/trust-and-governance/audit-log) | Capability | Audit log keeps every Action with who took it, for whom, under which Mandate and with what result, append-only and hash-chained. | | [Authenticated Actions](/systems/trust-and-governance/controls/authenticated-actions) | Control | Every Action runs under an authenticated identity, a Person or an agent Worker, recorded as its `by`. | | [Automated hiring](/systems/legal-and-corporate/floor/automated-hiring) | Legal floor row | Automated hiring gets an independent bias audit before an agent screens candidates, tells candidates ahead of use, and offers another process on request. | | [Automation terms](/systems/legal-and-corporate/floor/automation-terms) | Legal floor row | Automation terms keep every automated post, connection request, and Message within the published automation rules of the venue it runs on. | | [Autonomous](/agents/operating-models/autonomous) | Operating model | Autonomous is the operating model with no humans: Agents fill every Role, and one-way decisions wait out a delay window before they proceed. | | [Autonomous agent business](/start/templates/autonomous-agent) | Startup Template | An Autonomous agent business runs with no humans and sells Agent as a Service to businesses, people, and other Agents. | | [Autonomous data API](/start/templates/autonomous-data-api) | Startup Template | An Autonomous data API runs with no humans and sells a Dataset API and Headless SaaS to developers and their Agents. | | [Autonomous directory](/start/templates/autonomous-directory) | Startup Template | An Autonomous directory runs with no humans and sells listings in a Directory to Organizations that want buyers and Agents to find them. | | [Autonomous storefront](/start/templates/autonomous-storefront) | Startup Template | An Autonomous storefront runs with no humans and sells physical goods as a Dropship store to people and the Agents that shop for them. | | [AWS Marketplace](/workflows/plays#aws-marketplace) | Venue | AWS Marketplace is a marketplace Venue. | | [Azure Marketplace](/workflows/plays#azure-marketplace) | Venue | Azure Marketplace is a marketplace Venue. | | [b2a](/business/motions/b2a) | Motion | b2a is the Motion where an Agent finds, buys, and uses the Offer itself, paying within its own Limits. | | [b2a2b](/business/motions/b2a2b) | Motion | b2a2b is the Motion where an Agent buys the Offer on behalf of a business. | | [b2a2c](/business/motions/b2a2c) | Motion | b2a2c is the Motion where an Agent buys the Offer on behalf of a person. | | [b2a2d](/business/motions/b2a2d) | Motion | b2a2d is the Motion where an Agent buys the Offer on behalf of a developer. | | [b2b](/business/motions/b2b) | Motion | b2b is the Motion where a business buys the Offer and its people or Agents use it. | | [b2c](/business/motions/b2c) | Motion | b2c is the Motion where a person buys the Offer for their own use. | | [b2d](/business/motions/b2d) | Motion | b2d is the Motion where a developer buys the Offer to build it into their own Software. | | [b2h2a](/business/motions/b2h2a) | Motion | b2h2a is the Motion where a person buys the Offer and their Agent uses it. | | [Back-office outsourcing](/systems/integrations/upstreams#back-office-outsourcing) | Capability | Back-office outsourcing hands a whole back-office function to agents in the buyer’s Systems, with people resolving only the exceptions. | | [Background actions](/code/platform/queues) | Capability | Background actions run a Verb durably after the call returns, with retries, ordering and dead letters, and hand the caller an Action to watch. | | [Background checks](/systems/people/background-checks) | Capability | Background checks order lawful identity, criminal, credential and employment checks on candidates and Suppliers, with consent and required notices. | | [Backups](/code/platform/backups) | Capability | Backups keep point-in-time copies of every namespace, so any past state reads back and any Change reverts. | | [Bank accounts](/systems/finance/bank-accounts) | Capability | Bank accounts open the Company’s operating and reserve accounts, verify its owners, and feed every Transaction to the ledger. | | [Bank detail changes](/systems/trust-and-governance/controls/bank-detail-changes) | Control | Every change to a payout or payee bank is confirmed through a second channel, waits one business day, and notifies every owner. | | [Barrier reports](/workflows/processes/barrier-reports) | Process | Barrier reports fixes an accessibility barrier a person reports, or gives them an accessible alternative, within five business days. | | Behavior | Evidence grade | Behavior is an Evidence grade: what outside people did, the strongest grade. | | [Benchmark](/code/ui/components/benchmark) | Component | Benchmark ranks one Metric against a Cohort of peer Startups, with the 10th, 50th, and 90th percentiles. | | [Benefits](/systems/people/benefits) | Capability | Benefits set up and run employee health, retirement and other plans, with enrollment, payroll deductions and required plan filings. | | [BetaList](/workflows/plays#betalist) | Venue | BetaList is a launch site Venue. | | [Bill](/business/nouns/bill) | Noun | A Bill is an amount a Startup owes an outside Organization, coded to an account, approved within a Mandate, and paid by its due date. | | [Bill on confirmation](/workflows/processes/delivery/bill-on-confirm) | Workflow | Bill on confirmation captures and bills each Service Order line the Customer confirms, as the Outcome Contract’s `earns` names. | | [Bill.approve](/business/nouns/bill/approve) | Verb | Approve accepts a coded Bill for payment within the approver’s Mandate and schedules it for its due date. | | [Bill.pay](/business/nouns/bill/pay) | Verb | Pay sends an approved Bill’s amount to its Organization on the due date and reconciles the payment to Entries. | | [Billing](/workflows/processes/billing) | Process | Billing charges each Invoice when it is owed, recovers failed payments, and refunds within Limits. | | [Billing](/systems/billing) | System | Billing turns accepted Offers into Orders, Subscriptions, Invoices, metered usage and Entitlements on Stripe, with checkout and dunning. | | [Billing portal](/systems/finance/billing-portal) | Capability | Billing portal lets each Customer replace a card, fix billing details, download receipts, change plans and cancel, on the Startup’s own Domain. | | [Billing Specialist](/agents/finance/billing-specialist) | Role | The Billing Specialist bills, charges, and collects: it bills on done, retries failed payments, and refunds within its Limit. | | [Bing](/workflows/plays#bing) | Venue | Bing is a search Venue. | | [Biometrics](/systems/legal-and-corporate/floor/biometrics) | Legal floor row | Biometrics gets a written release before collecting a face, voice, or fingerprint template, publishes a retention schedule, and never sells one. | | [Board](/code/ui/components/board) | Component | Board groups one Noun's records into columns by state, and moving a record calls the Verb between those states. | | [Books](/workflows/processes/books) | Process | Books records every Transaction in one ledger, closes each Period, and files tax at the entity total. | | [Boundary protection](/systems/trust-and-governance/controls/boundary-protection) | Control | Every inbound request passes authentication and rate Limits, and every outbound call leaves through the gateway. | | [Brand](/business/nouns/brand) | Noun | A Brand is a name, a voice, a logo, and a style under which a Startup makes Offers. | | [Brand.clear](/business/nouns/brand/clear) | Verb | Clear checks a proposed Brand name against trademark registers, Domain availability and the Startup’s handles on outside platforms in one call. | | [Breach](/systems/legal-and-corporate/floor/breach) | Legal floor row | Breach reads what an Incident exposed, works out who must be told and by when, and drafts every notice the law requires. | | [Breach notification](/systems/trust-and-governance/controls/breach-notification) | Control | A personal data breach notifies every affected Person and authority within the legal deadline, scoped by an exact query. | | [Browser](/code/platform/browser) | Capability | Browser completes tasks in a real, recorded browser session wherever a site offers no programmatic access. | | [Budget](/business/nouns/budget) | Noun | A Budget is the amount a Startup plans to spend or earn on one account in one Period, read against actual Entries. | | [Budget](/workflows/processes/budget) | Process | Budget compares each month’s spend with its Budget, forecasts the next six months, and asks the Founder to approve every change to a Budget. | | [Builder](/business/nouns/builder) | Noun | A Builder is a named part of api.sb that builds one side of a Startup; StartupBuilder directs SiteBuilder, SoftwareBuilder, ServiceBuilder, and SalesBuilder. | | [Building](/business/lifecycle/states/building) | Lifecycle state | Building is the state of a Startup whose Agents build its Brand, Products, Offers, site, API, and MCP server from its template. | | [Buy from a vendor](/workflows/processes/procure/buy-from-vendor) | Workflow | Buy from a vendor turns a decision to buy into a reviewed upstream, a signed Agreement and a spending Mandate before the first charge. | | [Buying committee](/workflows/plays/buying-committee) | Play | Buying committee reaches every member of a named Organization’s buying committee through company-grain Ads, outbound and the Sales Team. | | [Call routing](/workflows/processes/call-routing) | Process | Call routing answers every call to the Startup’s numbers, routes it to the right Role, and promises a callback when no one is free. | | [CallToAction](/code/ui/components/call-to-action) | Component | CallToAction asks the reader to take one Verb, such as reserve, subscribe, or book, through one button. | | [Campaign](/business/nouns/campaign) | Noun | A Campaign is a bounded effort toward a Goal, with a budget, a window, and the Ads or Messages it sends to Audiences. | | [CAN-SPAM](/systems/legal-and-corporate/floor/can-spam) | Legal floor row | CAN-SPAM requires every commercial email, business mail included, to carry honest headers, an ad label, the Company’s postal address, and a working opt-out. | | [Cancel a subscription](/workflows/processes/plan-changes/cancel-subscription) | Workflow | Cancel a subscription ends renewal in one step, confirms the last day of access, and sends the Customer their data. | | [Candidate](/business/nouns/candidate) | Noun | A Candidate is a Person under consideration for an Opening, with the graded Evidence for and against them. | | [Candidate.screen](/business/nouns/candidate/screen) | Verb | Screen asks a Candidate only what the Opening’s Hypothesis still lacks, in writing, and grades each answer as Evidence. | | [Capability](/business/nouns/capability) | Noun | A Capability is a named set of Verbs on one Noun family that every Startup reaches through api.sb with one key, metered, limited, and logged. | | [Capacity headroom](/systems/trust-and-governance/controls/capacity-headroom) | Control | Capacity is forecast from use, and every Interface keeps headroom above its peak load. | | [Capterra](/workflows/plays#capterra) | Venue | Capterra is a directory Venue. | | [Card](/business/nouns/card) | Noun | A Card is a payment credential a Startup issues to one Worker under one Mandate, with controls compiled from that Mandate. | | [Card.issue](/business/nouns/card/issue) | Verb | Issue creates a Card under a Mandate once the Mandate check passes, with explicit limits on every interval. | | [Category hubs](/workflows/plays/category-hubs) | Play | Category hubs are owned directories that rank every product in a category by one published rule and route each Visitor to the best fit. | | [Category kit](/workflows/plays/category-kit) | Play | Category kit names the Problem a market does not search for yet, defines it for answer engines, and launches it on one dated day. | | [Certificates](/products/platform/certificates) | Capability | Certificates keep a valid TLS certificate on every serving Domain, renew it through delegated validation, and name the check that fails. | | [Change](/business/nouns/change) | Noun | A Change is a proposed set of writes to definitions, previewed on its own branch, checked, approved, and merged as one unit. | | [Change a plan](/workflows/processes/plan-changes/change-plan) | Workflow | Change a plan prorates the current period, moves the Customer’s Entitlements to the new Offer, and confirms the change. | | [Change approval](/systems/trust-and-governance/controls/change-approval) | Control | Every definition reaches production only through a merged Change, approved by a Worker at the required lineage distance from its author. | | [Change lead time](/agents/engineering#change-lead-time) | Metric | Change lead time is the hours from a Change opening to its deploy. | | [Change verdict](/code/verification/change-verdict) | Workflow | Change verdict tests each new proposal against its checks and known-good runs, then returns pass or fail, never an Approval. | | [Change.merge](/business/nouns/change/merge) | Verb | Merge applies a Change to live data with a three-way, field-level merge against its base Version. | | [Change.revert](/business/nouns/change/revert) | Verb | Revert undoes a merged Change with a new Change and a superseding Decision, deleting nothing. | | [Change.review](/business/nouns/change/review) | Verb | Review runs every Evaluator on a Change’s preview and records each verdict on the Change. | | [Changelog](/code/ui/components/changelog) | Component | Changelog lists published Content newest first, each item linked to the Version that shipped it. | | [Changelog](/code/systems/changelog) | System | Changelog publishes what shipped in each Version as dated notes on the Site, in feeds and to subscribed Customers. | | [Channel](/business/nouns/channel) | Noun | A Channel is a place Messages flow, such as a chat channel, a Mailbox, or an SMS number. | | [Chargebacks](/systems/legal-and-corporate/floor/chargebacks) | Legal floor row | Chargebacks watches each Startup’s daily dispute rate on the shared merchant account, refunds complainers early, and pauses paid ads past the act level. | | Chat app | Interface | A Chat app reaches a Product inside a chat workspace: its commands are the Product’s Verbs, and it ships through the workspace’s app directory. | | [Chat delivery](/systems/communications/chat) | Capability | Chat delivery posts and receives Messages in connected chat workspaces, carries buttons and forms, and links each chat account to a Worker or Contact. | | [ChatGPT](/workflows/plays#chatgpt) | Venue | ChatGPT is a search Venue. | | [Checkout](/systems/finance/checkout) | Capability | Checkout takes payment on a Startup’s own Domain through a hosted checkout page, payment links, a pricing table and an embedded payment form. | | [Checkout](/code/ui/components/checkout) | Component | Checkout sells one Offer on the page through Stripe, then shows the Order or Subscription it created. | | [Chrome Web Store](/workflows/plays#chrome-web-store) | Venue | Chrome Web Store is a marketplace Venue. | | [Claude](/workflows/plays#claude) | Venue | Claude is a search Venue. | | [CLI](/code/cli/reference) | Interface | The CLI runs every Verb from a shell, as a typed command per Verb or as `do Noun.verb` with JSON input. | | [Clinical practice](/systems/legal-and-corporate/floor/clinical-practice) | Legal floor row | Clinical practice sells care only through licensed clinicians and their own practices, licensed where the patient is, with no fee-splitting. | | [Close the loop](/workflows/processes/customer-research/close-the-loop) | Workflow | Close the loop tells each Customer whose Evidence a merged Issue addresses that it shipped, then grades whether they used it. | | [Closer handoff](/workflows/sales/plays/closer-handoff) | Play | Closer handoff brings a commissioned Human closer into a large Deal that stalled twice, paid only when it is won. | | [CMS](/systems/cms) | System | CMS holds authored Content, from posts to docs to legal Pages, with drafts, schedules and revisions, rendered on every Interface. | | [Cohort](/business/nouns/cohort) | Noun | A Cohort is a set of Startups that receives one Version of a shared definition, or one step of a Play, at the same time. | | [Cold email](/workflows/plays/cold-email) | Play | Cold email sends short Sequences to Prospects chosen by a dated signal, from secondary Domains, and pauses when complaints pass 0.1 percent. | | [Collection](/business/nouns/collection) | Noun | A Collection is a Thing with members, either listed one by one or defined by a saved query. | | [Collection.export](/business/nouns/collection/export) | Verb | Export writes a Collection’s records to a file or the Startup’s warehouse, once or on a schedule. | | [Collection.query](/business/nouns/collection/query) | Verb | Query reads any Nouns the caller’s Permissions allow, by SQL or a Relationship path, across every System in one call. | | [Comment](/business/nouns/comment) | Noun | A Comment is an internal note by a Worker about a Thing, never sent to a Contact. | | [Commerce](/systems/commerce) | System | Commerce is the opt-in System for Startups that sell physical goods by dropship: catalog, Orders, upstream fulfillment and shipment tracking. | | [Commission](/business/nouns/commission) | Noun | A Commission is what a Partner earns on the collected revenue its Referral brings, at a rate over a term, paid after a clawback window. | | [Commission partners](/workflows/plays/commission-partners) | Play | Commission partners pay publishers, creators and Agents a share of the collected, net-of-refund revenue they bring, after the refund window. | | [Commission.pay](/business/nouns/commission/pay) | Verb | Pay transfers a Commission’s earned, unpaid amount to the Partner’s connected account through Stripe. | | Commitment | Evidence grade | Commitment is an Evidence grade: what outside people offered: money, time, or an introduction. | | [Committed ICP members](/agents/founding#committed-icp-members) | Metric | Committed ICP members counts distinct outside ICP members whose Evidence on the Problem is commitment-grade or behavior-grade. | | [Common stock valuation](/systems/legal-and-corporate/valuation-409a) | Capability | Common stock valuation gets an independent appraisal of common stock before options are granted, refreshed yearly or after a financing. | | [Communications Lead](/agents/marketing/communications-lead) | Role | The Communications Lead answers the press, runs owned-account community engagement and events, and speaks for the Startup in a crisis. | | [Community answers](/workflows/plays/community-answers) | Play | Community answers solve questions where Customers already ask them, disclose affiliation, and post as an Agent only where the community allows Agents. | | [Company](/business/nouns/company) | Noun | A Company is a legal entity that holds Startups, signs Agreements, and owns equity, authority, and profit rights. | | [Company coverage](/systems/legal-and-corporate/insurance) | Capability | Company coverage obtains and renews the Company’s insurance policies, from general liability to cyber and directors and officers, sized to its risk. | | [Company dissolution](/systems/legal-and-corporate/entity-dissolution) | Capability | Company dissolution winds up a Company that no longer holds a business, filing final returns and its certificate while every record stays. | | [Company filings](/workflows/processes/company-filings) | Process | Company filings keeps the Company in good standing: it files each annual report, franchise tax and ownership report before its deadline. | | [Company formation](/systems/legal-and-corporate/entity-formation) | Capability | Company formation creates a Startup’s own Company: it records the entity-type Decision, files the certificate and appoints directors. | | [Company.dissolve](/business/nouns/company/dissolve) | Verb | Dissolve winds up a Company that holds no business: it files final returns and the certificate, and keeps every record. | | [Company.incorporate](/business/nouns/company/incorporate) | Verb | Incorporate forms a Company in a chosen jurisdiction, with its founders, shares and registered agent on record. | | [Company.register](/business/nouns/company/register) | Verb | Register applies for a sales tax, VAT or GST registration in one jurisdiction and records the grant as a Credential. | | [Company.submit](/business/nouns/company/submit) | Verb | Submit files one tax return for a jurisdiction and its Periods, pays the tax due, and keeps the return as a Document. | | [Comparative advertising](/systems/legal-and-corporate/floor/comparative-advertising) | Legal floor row | Comparative advertising names a competitor only truthfully, substantiates every claim before it runs, and uses their marks only to identify them. | | [Compile the demand kit](/workflows/processes/launches/compile-demand-kit) | Workflow | Compile the demand kit emits every asset the demand Plays read before the first one runs, each tagged with its lineage. | | [Compliance](/workflows/processes/compliance) | Process | Compliance proves every control holds, from the records the platform keeps as work happens. | | [Compliance](/systems/compliance) | System | Compliance maps controls to frameworks, tests each from the records every Action leaves, and publishes the trust center buyers read. | | [Compliance Officer](/agents/legal/compliance-officer) | Role | The Compliance Officer screens every Offer against the legal floor and keeps each control’s test passing. | | [Component](/business/nouns/component) | Noun | A Component is a named block of a Page, such as a hero, a pricing table, or a form, filled from records through typed props. | | [Compute openings](/workflows/processes/hiring/compute-openings) | Workflow | Compute openings reads each Role’s record every day and opens an Opening wherever a gap only a Human can close crosses its Setting. | | Concierge | Test ladder rung | Concierge delivers the outcome by hand to a few paying Customers, in the open. | | [Conduct](/systems/trust-and-governance/controls/conduct) | Control | Every Worker follows the Startup’s conduct rules, which Guards enforce: agents identify as agents, and each Human signs an acceptable-use Agreement. | | [Connect providers](/systems/integrations/provider-wiring/connect-providers) | Workflow | Connect providers wires a new Startup to the default provider of every capability it uses and tests each Integration. | | [Consent](/business/nouns/consent) | Noun | A Consent is a person’s grant for one Purpose, with its basis, region, notice, evidence, and expiry. | | [Consent.withdraw](/business/nouns/consent/withdraw) | Verb | Withdraw ends a Consent at once: processing for its Purpose stops, and the record is kept. | | [Consumer reports](/systems/legal-and-corporate/floor/consumer-reports) | Legal floor row | Consumer reports serves a report only for a permissible purpose, keeps it accurate, resolves disputes within 30 days, and sends adverse action notices. | | [Contact](/business/nouns/contact) | Noun | A Contact is a person or Agent a Startup knows by at least one address, where Consent to message them is recorded. | | [Contact.enrich](/business/nouns/contact/enrich) | Verb | Enrich fills a Contact’s missing fields from outside sources and marks each value with where it came from. | | [Contact.enroll](/business/nouns/contact/enroll) | Verb | Enroll adds a Contact to a Sequence, which sends its steps until the Contact replies or exits. | | [Contact.merge](/business/nouns/contact/merge) | Verb | Merge joins a duplicate Contact into another, keeping every link, Message and Event on the one that remains. | | [Contact.subscribe](/business/nouns/contact/subscribe) | Verb | Subscribe records a Contact’s chosen topics and frequency from the hosted preference page, with Consent for each topic. | | [Contact.suppress](/business/nouns/contact/suppress) | Verb | Suppress records a Suppression for a Contact’s address, which every Startup honors forever. | | [Contact.unsubscribe](/business/nouns/contact/unsubscribe) | Verb | Unsubscribe stops commercial Messages to a Contact in one click, for one topic or all, honored at once. | | [Content](/business/nouns/content) | Noun | Content is authored material with a draft and a published state, such as a post, an article, or a changelog entry. | | [Content Lead](/agents/marketing/content-lead) | Role | The Content Lead writes and publishes the Pages, answers, and data reports that search engines and answer engines cite. | | [Content marketing](/workflows/processes/content-marketing) | Process | Content marketing publishes the Pages, answers, and data reports that bring buyers and Agents to a Startup. | | [Content.draft](/business/nouns/content/draft) | Verb | Draft writes Content of one kind from a brief, such as an article for a question the help center could not answer. | | [Content.publish](/business/nouns/content/publish) | Verb | Publish puts a Content draft live on its Site and every Interface, once it passes the Evals for its kind. | | [Continuity](/workflows/processes/continuity) | Process | Continuity sets recovery objectives per Capability, fails over between upstreams, names a successor signer, and runs restore drills on a cadence. | | [Continuous control testing](/systems/trust-and-governance/controls/continuous-testing) | Control | Each automated control’s test runs daily over its whole population and records its result against a published root. | | [Contract cycle time](/agents/legal#contract-cycle-time) | Metric | Contract cycle time is the days from an Agreement’s first draft to its signature. | | [Contracting](/workflows/processes/contracting) | Process | Contracting covers every Agreement the Startup offers or signs, from its published terms to a negotiated contract. | | [Contractor payments](/systems/finance/contractor-payments) | Capability | Contractor payments onboard contractors and human supply, collect their tax forms, pay accepted work and file year-end information returns. | | [Contracts Manager](/agents/legal/contracts-manager) | Role | The Contracts Manager drafts, negotiates within set fallbacks, and stores every Agreement the Startup signs. | | [Contribution margin](/agents/finance#contribution-margin) | Metric | Contribution margin is a paid Offer’s outside revenue minus the Costs its delivery and acquisition post, as a share of that revenue. | | [Contribution per outcome](/agents/finance#contribution-per-outcome) | Metric | Contribution per outcome is outside revenue minus delivery and acquisition Costs, divided by the accepted outcomes in the window. | | [Control](/business/nouns/control) | Noun | A Control is a rule the platform enforces on every write it covers, with a test that runs over the whole population. | | [Control definition](/systems/trust-and-governance/controls/control-definition) | Control | Every control declares a test, at least one criterion and at least one implementer before it merges. | | [Control sameness](/systems/trust-and-governance/controls/control-sameness) | Control | Every namespace in scope runs the tested Version of each inherited control, or the difference is listed by Change. | | [Control testing](/workflows/processes/compliance/evidence-collection) | Workflow | Control testing runs each control’s test against the platform’s records every day and opens an Issue for each failure. | | [Control wake review](/systems/trust-and-governance/controls/control-wake-review) | Control | A definition Change that wakes a control opens a Task for that control’s owner before it merges. | | [Conversation](/business/nouns/conversation) | Noun | A Conversation is a Thread with one or more Contacts that a Worker must answer, such as a support request. | | [Conversation.answer](/business/nouns/conversation/answer) | Verb | Answer replies in a Conversation through the Channel it arrived on and closes the reply Task it opened. | | [Conversation.assign](/business/nouns/conversation/assign) | Verb | Assign routes a Conversation to the Worker holding the right Role, by topic, Customer tier and language. | | [Conversation.close](/business/nouns/conversation/close) | Verb | Close marks a Conversation resolved, confirmed by the Customer or assumed after 72 hours with no reply. | | [Conversation.escalate](/business/nouns/conversation/escalate) | Verb | Escalate hands a Conversation and its summary to the Worker in the Role above, a Human only where one holds it. | | [Conversation.reopen](/business/nouns/conversation/reopen) | Verb | Reopen reverses a Conversation’s resolution when a reversal signal arrives within 7 days, and grades the resolution a failure. | | [Convert a trial](/workflows/processes/plan-changes/convert-trial) | Workflow | Convert a trial reminds each Customer before their trial ends and converts it to paid, or ends it, on the Offer’s terms. | | [Corporate cards](/systems/finance/cards) | Capability | Corporate cards issue virtual and physical cards to Workers and agents, each bound to a Mandate, merchant rules and Limits. | | [Corporate records](/systems/corporate-records) | System | Corporate records keeps the legal Company behind a Startup: formation, officers, registered office, filings, board resolutions and good standing. | | [Cost](/business/nouns/cost) | Noun | A Cost is an Entry against a cost account that an Action causes, posted to the Startup the Action ran in. | | [Cost coverage](/agents/finance#cost-coverage) | Metric | Cost coverage is outside revenue divided by fully loaded Cost over the same window; 1 or more means revenue pays for the Startup. | | [Coupon](/business/nouns/coupon) | Noun | A Coupon is a discount on Offers, by amount or percent, for one charge, several months or every charge, limited by date and redemptions. | | [Creator ads](/workflows/plays/creator-ads) | Play | Creator ads promote a creator’s winning post as a paid Ad under partnership rights, at or above the minimum effective budget. | | [Creator partnership](/workflows/plays/creator-partnership) | Play | Creator partnership signs creators on one ladder, from referral terms to paid post, co-branded Offer and cofounder, each paid on attributed collected revenue. | | [Creator probe](/workflows/plays/creator-probe) | Play | Creator probe pays five to ten small creators $50 to $500 each for one post, each post a pre-registered arm of one Experiment. | | [Credential](/business/nouns/credential) | Noun | A Credential is a standing authority a regulator grants a person or entity to perform certain acts in a jurisdiction. | | [Credential check](/workflows/processes/supply/credential-check) | Workflow | Credential check confirms every Supplier’s standing each day and suspends a Supplier the same day its standing lapses. | | [Credential.verify](/business/nouns/credential/verify) | Verb | Verify confirms a Credential with the authority that issued it and records when it expires. | | [Credentialing](/systems/credentialing) | System | Credentialing verifies each Supplier’s Credentials with the issuer, tracks expiry, and decides who may perform a Reserved Act. | | [Credit Grant](/business/nouns/credit-grant) | Noun | A Credit Grant is a prepaid or promotional balance a Customer spends on a Startup’s metered Offers, checked before each call. | | [CreditGrant.apply](/business/nouns/credit-grant/apply) | Verb | Apply spends Credit Grants against a finalizing Invoice, promotional first, then by priority and earliest expiry, and settles them through Stripe credit grants. | | [CreditGrant.issue](/business/nouns/credit-grant/issue) | Verb | Issue gives a Customer a paid or promotional Credit Grant that its metered calls draw down before anything is invoiced. | | [CreditGrant.void](/business/nouns/credit-grant/void) | Verb | Void ends a promotional Credit Grant early and forfeits its remaining balance, keeping the record. | | [Credits](/systems/finance/credits) | Capability | Credits let a Customer prepay or receive a balance that its metered calls draw down, checked before each call and settled on the Invoice. | | [Criterion](/business/nouns/criterion) | Noun | A Criterion is one requirement of an outside framework, such as SOC 2 or GDPR, that one or more Controls satisfy. | | [CRM](/systems/crm) | System | CRM keeps the Contacts and Organizations a Startup knows, every Lead, and the Deals it pursues with them. | | [Customer](/business/nouns/customer) | Noun | A Customer is a party that has accepted an Offer from a Startup at any price, including zero. | | [Customer access](/systems/customer-access) | System | Customer access governs who acts in each Customer’s Tenant: members, invitations, Roles, Permissions, sign-in connections, directory sync and keys. | | [Customer health](/agents/customer#customer-health) | Metric | Customer health is the share of outside paying Customers whose computed status is not `atRisk` at the window’s end. | | [Customer Lead](/agents/customer/customer-lead) | Role | The Customer Lead owns every Conversation and the single Thread each Person has with the Startup. | | [Customer referrals](/workflows/plays/customer-referrals) | Play | Customer referrals invite a Customer’s peers after a delivered outcome and pay the reward only on the peer’s paid, unrefunded Order. | | [Customer research](/workflows/processes/customer-research) | Process | Customer research learns from what buyers did and paid, never from their predictions. | | [Customer Team](/agents/customer) | Team | The Customer Team serves every Customer after the first acceptance: onboarding, support, retention, and the one Thread each Person has. | | [Customer.activate](/business/nouns/customer/activate) | Verb | Activate marks a Customer activated on an Offer once its declared activation Event reaches the count within the window. | | [Customer.exempt](/business/nouns/customer/exempt) | Verb | Exempt records a Customer’s exemption or resale certificate, verifies it, and stops tax on its Orders where the certificate applies. | | [Daily ship](/workflows/processes/shipping/daily-ship) | Workflow | Daily ship ranks misses, requests, and steps done by hand three times, then ships the top Issue as one small Change. | | [Dashboard](/business/nouns/dashboard) | Noun | A Dashboard is one unified view of a scope, rendered as Markdown for Agents, screens for Humans, and JSON for native clients. | | [Dashboard.ask](/business/nouns/dashboard/ask) | Verb | Ask answers a plain-language question with a query over the Startup’s records and shows the query beside the result. | | [Dashboard.schedule](/business/nouns/dashboard/schedule) | Verb | Schedule sends a Dashboard on a cadence to a Mailbox, a Channel or an Agent’s context, rendered for each. | | [Data broker](/systems/legal-and-corporate/floor/data-broker) | Legal floor row | Data broker registers the Company in each state broker registry once it sells personal data about people it has no direct relationship with. | | [Data editor](/code/systems/data-editor) | System | Data editor edits a Startup’s own Nouns directly: tables, saved views, imports, exports and bulk Changes. | | [Data Engineer](/agents/engineering/data-engineer) | Role | The Data Engineer sources, licenses, and refreshes the Datasets a Startup sells, and keeps their quality measured. | | [Data residency](/workflows/sales/plays/data-residency) | Play | Data residency pins a buyer’s Tenant to one region, adds the residency annex, and quotes the Price tier that includes it. | | [Data stories](/workflows/plays/data-stories) | Play | Data stories pitch original data to journalists and researchers, scored by mentions on the domains answer engines cite. | | [Database](/code/platform/capabilities/database) | Capability | Database stores every Thing in an owner database per namespace, with an analytics copy of every Event and reads at any past moment. | | [Dataset](/business/nouns/dataset) | Noun | A Dataset is a Product of curated Things of one Noun, with a promise that they are true. | | [Dataset API](/products/templates/dataset-api) | Product Template | A Dataset API sells keyed lookups and queries over a Dataset to developers and Agents, metered per call. | | [Dataset freshness](/agents/engineering#dataset-freshness) | Metric | Dataset freshness is the share of Datasets refreshed on their promised schedule. | | [Datasets](/systems/datasets) | System | Datasets is the System behind each Dataset: curated Things of one Noun, built from Sources plus enrichment, refreshed and checked against its promise. | | [DataTable](/code/ui/components/data-table) | Component | DataTable lists one Noun's records in chosen columns; rolled up across scopes, it adds a scope column instead of averaging. | | [Days sales outstanding](/agents/finance#days-sales-outstanding) | Metric | Days sales outstanding is the average days from an Invoice being sent to its payment. | | [Days to first outside Order](/agents/founding#days-to-first-outside-order) | Metric | Days to first outside Order counts the days from Live entry to the first paid Order from an outside Customer. | | [db.sb](/code/platform/db-sb) | Product | db.sb is the one database behind api.sb, keeping every record and event of every Startup. | | [Deal](/business/nouns/deal) | Noun | A Deal is a Startup’s pursuit of one buyer’s acceptance of one or more Offers, ending won or lost. | | [Deal.advance](/business/nouns/deal/advance) | Verb | Advance moves a Deal to its next stage once every field that stage requires is filled. | | [Deal.assign](/business/nouns/deal/assign) | Verb | Assign gives a Deal one owner Worker, who carries its next step until it is won or lost. | | [Deal.lose](/business/nouns/deal/lose) | Verb | Lose closes a Deal as lost and records the reason the buyer gave. | | [Deal.propose](/business/nouns/deal/propose) | Verb | Propose sends a Deal’s buyer a Quote they accept to place an Order. | | [Deal.win](/business/nouns/deal/win) | Verb | Win closes a Deal as won, which places its Order and makes the buyer a Customer. | | [Debt collection](/systems/legal-and-corporate/floor/debt-collection) | Legal floor row | Debt collection sends a validation notice, caps contact frequency, and never harasses or misleads when a Startup collects debts owed to others. | | [Decision](/business/nouns/decision) | Noun | A Decision is the immutable record of a choice: its options, the choice, the reason, who decided, and the stakes. | | [Decision.supersede](/business/nouns/decision/supersede) | Verb | Supersede replaces a Decision with a newer one, keeping both on record with the reason for the change. | | [Declared Verb attempts](/agents/product#declared-verb-attempts) | Metric | Declared Verb attempts counts live calls in 7 days to each Verb no Function runs yet, ranking which Function to build next. | | [Default alive](/agents/founding#default-alive) | Metric | Default alive is runway divided by the months to profit at current growth and fully loaded Cost; 1 or more reads alive. | | [Default-alive check](/workflows/processes/runway/default-alive-check) | Workflow | Default-alive check forecasts cash and growth forward each week and reports whether the Startup reaches profit first. | | [Define a Product](/workflows/processes/product-definition/define-product) | Workflow | Define a Product turns an Offer’s promise into the Nouns and Verbs that every Interface, Page, and Tool is generated from. | | [Delegated sending](/systems/legal-and-corporate/floor/delegated-sending) | Legal floor row | Delegated sending lets an Agent send as a Human only under that Human’s Mandate, with the disclosure each jurisdiction’s bot law requires. | | [Deliver an outcome](/workflows/processes/delivery/deliver-outcome) | Workflow | Deliver an outcome runs the work an Order bought, gets it confirmed, redoes it once on a miss, and bills only when done. | | [Delivery](/workflows/processes/delivery) | Process | Delivery runs the Orders Customers place for Agent and Service outcomes, and bills only on confirmation. | | [Delivery Manager](/agents/operations/delivery-manager) | Role | The Delivery Manager runs each Order a Customer places, gets it confirmed, redoes it once on a miss, and bills only when done. | | [Demand Budget](/business/nouns/demand-budget) | Noun | A Demand Budget is the money a founder commits each month to demand Plays, recorded as a Decision with a target and a stop rule. | | [Demand generation](/systems/integrations/upstreams#demand-generation) | Capability | Demand generation runs demand Plays for a Startup inside its own Systems and attributes the revenue each one earns. | | [Deploy reconciliation](/systems/trust-and-governance/controls/deploy-reconciliation) | Control | Only Versions a merged Change points to run, and any other running fingerprint opens an Incident. | | [Design first run](/workflows/processes/product-definition/design-first-run) | Workflow | Design first run compiles sample records, empty states and the shortest path to an Offer’s activation event from the definition. | | [Designer](/agents/product/designer) | Role | The Designer shapes every App and Site a Startup ships, as data that renders for Humans and Agents alike. | | [Developer relations](/workflows/plays/developer-relations) | Play | Developer relations publishes examples, docs and answers that get a developer or Agent to a first successful call within five minutes. | | [Deviation closure](/systems/trust-and-governance/controls/deviation-closure) | Control | A failed test opens an Issue that closes only by a Decision recording cause, remediation and management’s response. | | [Directory](/products/templates/directory) | Product Template | A Directory sells listings: Organizations pay to appear in a searchable Dataset that buyers and their Agents browse free. | | [Directory listings](/workflows/plays/directory-listings) | Play | Directory listings keep a Startup listed and accurate on review sites, business profiles and vertical directories, free from the day it is Live. | | [Disclosure record](/systems/trust-and-governance/controls/disclosure-record) | Control | Every disclosure of personal data to a third party is an Event that cites its Agreement and Purpose. | | [Discovery](/business/discovery) | System | Discovery runs buyer research: Interviews, Problems, graded Evidence, ICPs and Personas, so every Offer starts from what buyers said. | | [Discussions](/agents/discussions) | System | Discussions gives Workers and Contacts headless Channels and Threads, where a mention assigns a reply Task and an Approval arrives with buttons. | | [Dispatch](/systems/dispatch) | System | Dispatch proposes each job to eligible, available Suppliers, books shifts, and proposes it again on decline before the deadline. | | [Dispute](/business/nouns/dispute) | Noun | A Dispute is a contested payment or delivery, such as a chargeback, a rejected Service outcome, or a buyer’s claim against a Supplier. | | [Dispute response](/systems/finance/dispute-response) | Capability | Dispute response answers chargebacks and contested deliveries with the Startup’s own records as Evidence, under each Dispute kind’s rules and deadlines. | | [Dispute.accept](/business/nouns/dispute/accept) | Verb | Accept concedes an open Dispute without contest, so the buyer keeps the held amount and the Dispute closes. | | [Dispute.answer](/business/nouns/dispute/answer) | Verb | Answer submits the seller’s Evidence on an open Dispute before its deadline: the contract, the delivered work, and its verdicts. | | [Dispute.appeal](/business/nouns/dispute/appeal) | Verb | Appeal asks for one review of a decided Dispute by a Worker who took no part in the first decision. | | [Dispute.decide](/business/nouns/dispute/decide) | Verb | Decide rules on an answered Dispute for the buyer, the seller, or a split, and releases or returns the held amount. | | [DNS](/products/platform/dns) | Capability | DNS serves each Domain’s records as data, signs every zone with DNSSEC, and flags missing, drifted or dangling records daily. | | [DNS Record](/business/nouns/dns-record) | Noun | A DNS Record is one DNS answer of a Domain: its type, name and value, who owns it, and what the world last answered. | | [DNSRecord.remove](/business/nouns/dns-record/remove) | Verb | Remove stops a Startup-owned DNS Record from answering; its history stays and a revert restores it. | | [DNSRecord.set](/business/nouns/dns-record/set) | Verb | Set adds or changes a Startup-owned DNS Record through a Change, previewed against what the Domain answers today. | | [Document](/business/nouns/document) | Noun | A Document is structured, versioned material in one of three forms, a document, a deck, or a sheet, rendered to any format. | | [Document.render](/business/nouns/document/render) | Verb | Render produces a file from a Document in the format the reader asks for. | | [Documents](/code/systems/documents) | System | Documents keeps every versioned Document, deck or sheet, generated from records and rendered to the web, PDF, slides or spreadsheets. | | [Domain](/business/nouns/domain) | Noun | A Domain is a hostname that points at a Thing, with a role, a status, and a lifecycle tracked as data. | | [Domain registration](/products/platform/domain-registration) | Capability | Domain registration registers and renews each Startup’s Domains in a registrar account of its own, with its owner of record as registrant. | | [Domain.authenticate](/business/nouns/domain/authenticate) | Verb | Authenticate writes a Domain’s SPF, DKIM and DMARC records and verifies them before its first send. | | [Domain.benchmark](/business/nouns/domain/benchmark) | Verb | Benchmark measures a Domain’s estimated traffic, ranking Keywords, authority and referring domains beside the competitors named. | | [Domain.claim](/business/nouns/domain/claim) | Verb | Claim gives a Startup a one-label name under an issuing Domain, or assigns it a held Domain through an approved Change. | | [Domain.connect](/business/nouns/domain/connect) | Verb | Connect attaches a hostname a Startup already holds and verifies ownership through DNS. | | [Domain.register](/business/nouns/domain/register) | Verb | Register buys a hostname for a Startup and points it at the Startup’s address. | | [Domain.release](/business/nouns/domain/release) | Verb | Release lets a Domain’s registration or claim end, keeping its record, history and aliases. | | [Domain.renew](/business/nouns/domain/renew) | Verb | Renew extends a Domain’s registration by whole years at its renewal price, paid by its owner of record. | | [Domain.search](/business/nouns/domain/search) | Verb | Search lists candidate names with availability, first-year price, renewal price and the rules of each extension. | | [Domain.transfer](/business/nouns/domain/transfer) | Verb | Transfer moves a Domain’s registration to another holder or registrar, with its records intact. | | [Domain.verify](/business/nouns/domain/verify) | Verb | Verify checks a Domain’s DNS, ownership and certificate again and records each result, with the fix for any failure. | | [Domains](/products/platform/domains) | Capability | Domains connect names, DNS Records and certificates to a Startup’s Sites, Apps, Interfaces and Mailboxes, signed with DNSSEC by default. | | [Dormant](/business/lifecycle/states/dormant) | Lifecycle state | Dormant is the state of a Startup with no work running on it, whose records, site, and domain stay kept until it returns to Live. | | [Drill a restore](/workflows/processes/continuity/drill-restore) | Workflow | Drill a restore restores each Capability’s records in isolation on its cadence, checks both recovery objectives, and opens an Issue on a miss. | | [Dropship store](/products/templates/dropship-store) | Product Template | A Dropship store sells physical goods from a catalog while an upstream holds the stock and ships each Order, with tracking passed through. | | [Dunning](/workflows/processes/billing/dunning) | Workflow | Dunning retries failed payments on a schedule, tells the Customer once per retry, and pauses access only after the last attempt. | | [E2E managed service](/products/templates/managed-service) | Product Template | An E2E managed service runs a whole business function for the Customer, with Agents doing the work and Humans in the loop. | | [Earned mentions](/agents/marketing#earned-mentions) | Metric | Earned mentions counts the articles, Posts and podcasts each month that name the Startup without being paid. | | [Earnings](/systems/payouts) | System | Earnings pays Suppliers, Partners and affiliates their earnings through Stripe, holds disputed amounts, and sends statements and year-end tax filings. | | [Editorial SEO](/workflows/plays/editorial-seo) | Play | Editorial SEO publishes guides, comparisons and alternative Pages that rank for searches a market already makes, refreshed on a fixed cadence or pruned. | | [Eligibility](/systems/legal-and-corporate/floor/eligibility) | Legal floor row | Eligibility refuses any declared use of Person data to decide credit, insurance, employment, or housing unless the Product is built as a consumer report. | | [Email delivery](/systems/communications/email) | Capability | Email delivery sends and receives email from warmed, authenticated Mailboxes, and checks Consent and Suppression before every send. | | [Email routing](/products/platform/email-routing) | Capability | Email routing receives mail for a Startup’s Domains, routes each address to a Mailbox or the sink, and publishes SPF, DKIM and DMARC. | | [Employment eligibility](/systems/people/employment-eligibility) | Capability | Employment eligibility verifies each new employee’s right to work, records the employer’s attestation and keeps it for its retention period. | | [Encryption](/code/platform/encryption) | Capability | Encryption protects every namespace in transit and at rest under its own keys, rotated on schedule with every old key kept. | | [Encryption](/systems/trust-and-governance/controls/encryption) | Control | Every record is encrypted at rest under its namespace’s key, and every connection is encrypted in transit. | | [Endorsements](/systems/legal-and-corporate/floor/endorsements) | Legal floor row | Endorsements bans fake or bought reviews and requires every Referral payment, insider review, and sibling recommendation to disclose its connection. | | [Engagement bridge](/workflows/plays/engagement-bridge) | Play | Engagement bridge answers public questions from disclosed agent accounts and sends a direct Message only to a Person who engaged, quoting that act. | | [Engineering Lead](/agents/engineering/engineering-lead) | Role | The Engineering Lead builds and runs the Startup’s Products: it implements each Change, deploys it behind replay, and owns uptime of every Interface. | | [Engineering seals](/systems/legal-and-corporate/floor/engineering-seals) | Legal floor row | Engineering seals has a licensed engineer or architect in the project’s state seal every drawing or report the law reserves to them. | | [Engineering Team](/agents/engineering) | Team | The Engineering Team builds and runs every Product: it implements Nouns and Verbs, ships Changes behind replay, and keeps every Interface up. | | [Enrichment](/systems/sales/enrichment) | Capability | Enrichment finds and fills in people and Organizations, with provenance on every field and Suppression checked first. | | [Enrollment](/business/nouns/enrollment) | Noun | An Enrollment is one person’s run through one Sequence: the current step, when the next fires, the branches taken, and why it ended. | | [Enrollment.cancel](/business/nouns/enrollment/cancel) | Verb | Cancel ends one Contact’s run through a Sequence for good, with the reason it records as `exitReason`. | | [Enrollment.pause](/business/nouns/enrollment/pause) | Verb | Pause stops one Contact’s run through a Sequence at its current step, without ending it. | | [Enrollment.resume](/business/nouns/enrollment/resume) | Verb | Resume restarts a paused run at the step it stopped on and sets when that step fires. | | [Entitlement](/business/nouns/entitlement) | Noun | An Entitlement is what a Customer gets from an accepted Offer: a Verb on a Noun in its Tenant, optionally bounded by a Limit. | | [Entitlement.check](/business/nouns/entitlement/check) | Verb | Check says whether a Customer may call a Verb now, how much of its Limit remains, when that resets, and which Offer lifts it. | | [Entry](/business/nouns/entry) | Noun | An Entry is one line of a double-entry posting: an amount to one account in the chart of accounts, caused by one Event. | | [Entry.post](/business/nouns/entry/post) | Verb | Post records a manual Entry pair that no Verb caused, once a second Role approves it. | | [Entry.settle](/business/nouns/entry/settle) | Verb | Settle nets a Period’s intercompany Entries between two Companies into one transfer through Stripe and reconciles both sides. | | [Environment separation](/systems/trust-and-governance/controls/environment-separation) | Control | Actions in test never touch live records, move real money or send Messages to a real Person. | | [Environments](/code/platform/environments) | Capability | Environments give every namespace a test and a live environment, with separate keys, records and money over one shared definition. | | [Equity](/systems/equity) | System | Equity is the core System that keeps the cap table of each Company: shares, SAFEs, options and their holders, grants, vesting and conversions. | | [Escaped defects](/agents/quality#escaped-defects) | Metric | Escaped defects counts the Issues a Customer reports each week that an existing check should have caught. | | [Evals](/agents/evals-system) | System | Evals grades outputs with versioned Evaluators, gates every Change before merge, and keeps each Worker’s track record. | | [Evaluator](/business/nouns/evaluator) | Noun | An Evaluator is a versioned Function that grades an output against a rubric and returns a verdict. | | [Event](/business/nouns/event) | Noun | An Event is the immutable record of something that happened to a Thing, named by its Noun and past-tense Verb. | | [Event streams](/code/platform/event-streams) | Capability | Event streams record every completed Action as an immutable Event and deliver it, in order, to subscribers, Watches and replays. | | [Event.capture](/business/nouns/event/capture) | Verb | Capture records an Event from a Site, App or API call that no Verb emits, such as a page view or a click. | | [Events and webinars](/workflows/plays/events-and-webinars) | Play | Events and webinars host sessions for mid-market and enterprise Customers, turn each into on-demand content, and enroll attendees in a Sequence within a day. | | [Evidence](/business/nouns/evidence) | Noun | Evidence is a recorded quote, reading, or artifact that supports or refutes a claim, graded as behavior, commitment, or opinion. | | [Evidence-backed Decisions](/agents/product#evidence-backed-decisions) | Metric | Evidence-backed Decisions is the share of product Decisions that cite at least one piece of Evidence from buyers. | | [Expansion revenue](/agents/customer#expansion-revenue) | Metric | Expansion revenue is the recurring revenue outside Customers paying at the window’s start add in it: more units, a higher Price or another Offer. | | [Expense approval](/workflows/processes/expense-approval) | Process | Expense approval checks every card charge against its Mandate and the spender’s Limit, asks the Founder above it, and codes each charge with its receipt. | | [Experiment](/business/nouns/experiment) | Noun | An Experiment is a test of a Hypothesis that varies copy or behavior through Flags and judges the variants by a primary Metric. | | [Experiment.conclude](/business/nouns/experiment/conclude) | Verb | Conclude ends an Experiment with a decision to ship, kill, or iterate, recorded as a Decision. | | [Experiment.start](/business/nouns/experiment/start) | Verb | Start opens an Experiment, splits traffic across its variants, and begins measuring its primary and guardrail Metrics. | | [Experimentation](/workflows/processes/experimentation) | Process | Experimentation tests one change against a control, with the threshold fixed before the start. | | [Experiments](/systems/experiments) | System | Experiments tests Hypotheses by varying copy, Price or behavior through Flags and decides each winner from primary and guardrail Metrics. | | [Export controls](/systems/legal-and-corporate/floor/export-controls) | Legal floor row | Export controls classifies Software with encryption before export and refuses delivery to embargoed destinations and listed parties. | | [Exposure](/business/nouns/exposure) | Noun | An Exposure is the moment one unit meets the Variant its Flag assigned, logged with every option and its propensity. | | [Facebook](/workflows/plays#facebook) | Venue | Facebook is a social Venue. | | Fake door | Test ladder rung | Fake door adds a coming-soon Offer to a live Site and counts the clicks on it. | | [Fan out an outcome](/workflows/processes/retention/fan-out-outcome) | Workflow | Fan out an outcome turns one confirmed Customer outcome into a dated number, and with Consent into a case study, quote and referral invite. | | [Faq](/code/ui/components/faq) | Component | Faq answers buyer questions in pairs, each answer filled from a record so it matches the live Offer. | | [Features](/code/ui/components/features) | Component | Features lists what a Product does, one short line each, drawn from its Nouns and Verbs. | | [File](/business/nouns/file) | Noun | A File is the stored bytes of an upload or a rendering. | | [File the annual report](/workflows/processes/company-filings/annual-report) | Workflow | File the annual report drafts each annual report, franchise tax and ownership report from the record and files it before its deadline. | | [File.edit](/business/nouns/file/edit) | Verb | Edit makes a new File from an existing one by instruction, such as upscaling or animating a still, and leaves the source unchanged. | | [File.generate](/business/nouns/file/generate) | Verb | Generate makes an image, video, speech or music File from a prompt and reference Files, and records how it was made. | | [Files](/code/systems/files) | System | Files holds the stored bytes of each upload or rendering, versioned, with share links. | | [Fill rate](/agents/operations#fill-rate) | Metric | Fill rate is the share of requested Orders a Supplier accepts and starts within the promised time. | | [Finance Lead](/agents/finance/finance-lead) | Role | The Finance Lead keeps the books: it closes each Period, reports tax at the entity total, and sets the money Limits every Role works within. | | [Finance Team](/agents/finance) | Team | The Finance Team moves and records the money: Invoices, dunning, refunds within a Limit, payouts, the monthly close, tax, and runway. | | [Financial accounts](/systems/finance/financial-accounts) | Capability | Financial accounts hold a Startup’s cash on Stripe, move it between its cash accounts and out to banks, and post every movement to the ledger. | | [Financial privacy](/systems/legal-and-corporate/floor/financial-privacy) | Legal floor row | Financial privacy gives a privacy notice, honors opt-outs from sharing, and runs a written security program wherever a Startup is a financial institution. | | [First response time](/agents/customer#first-response-time) | Metric | First response time is the median business hours from a Conversation’s first Message to its first answer. | | [First responses on time](/agents/customer#first-responses-on-time) | Metric | First responses on time is the share of Conversations first answered before their `respondBy` time. | | [Fix a barrier](/workflows/processes/barrier-reports/fix-barrier) | Workflow | Fix a barrier gives the reporter an accessible alternative at once and fixes the Page, App or document within five business days. | | [Flag](/business/nouns/flag) | Noun | A Flag is a switch, evaluated per Visitor, Customer, or request, that selects which copy or behavior they get. | | Flag split | Test ladder rung | Flag split randomizes Variants of the built thing behind a Flag and reads each against the control. | | [Flag.evaluate](/business/nouns/flag/evaluate) | Verb | Evaluate returns the Variant a Flag assigns one unit, the same one every time, and records the Exposure with every option and its propensity. | | [Flags](/systems/flags) | System | Flags decides which copy or behavior each Visitor, Customer or request gets, by rules and sticky splits evaluated at the edge. | | [Flow](/business/nouns/flow) | Noun | A Flow is an ordered path through an App’s Dashboards that takes one Persona from first run to an Offer’s activation Event. | | [Footer](/code/ui/components/footer) | Component | Footer closes every Page with navigation, the Brand, and links to the locked terms and privacy Pages. | | [Forecast](/business/nouns/forecast) | Noun | A Forecast is a dated week-by-week projection of a Startup’s cash, revenue and Cost, computed from its records, that sets its spend state. | | [Foreign qualification](/systems/legal-and-corporate/foreign-qualification) | Capability | Foreign qualification registers the Company in each other state where it has employees or presence, and keeps each registration in good standing. | | [Form](/business/nouns/form) | Noun | A Form is a set of fields someone fills in on a Site or in a Message, producing a Lead, Evidence, or a Thing. | | [Form a company](/workflows/processes/incorporation/form-company) | Workflow | Form a company files the certificate, appoints a registered agent, gets a tax id, opens a bank account and issues founder shares. | | [Forms](/systems/forms) | System | Forms collects structured answers on a Site or in a Message and routes each submission to a Lead, Evidence or another Thing. | | [Founder](/agents/founding/founder) | Role | The Founder is the Startup’s decider: it owns the strategy, sets the Goals, and rules on every Task another Role escalates. | | [Founder Run](/code/founder-run) | Process | Founder Run walks every Startup Template through its published Interfaces in test, as a synthetic founder and buyers, and records each step that stops. | | [Founder voice](/workflows/plays/founder-voice) | Play | Founder voice posts on a human founder’s own LinkedIn and X under a posting Mandate, each post drafted from the record and approved. | | [Founder-led marketplace](/start/templates/founder-marketplace) | Startup Template | A Founder-led marketplace has one Human founder who signs for a Marketplace, while Agents recruit Suppliers and serve buyers. | | [Founding documents](/systems/legal-and-corporate/founding-documents) | Capability | Founding documents give a new Company its bylaws, initial consents, founder stock, vesting, invention assignments and tax elections. | | Founding Hypothesis | Hypothesis kind | The Founding Hypothesis is the root Hypothesis a Startup authors first: one sentence with five slots, each graded by outside Evidence. | | [Founding Team](/agents/founding) | Team | The Founding Team decides what the Startup pursues: its Idea, its strategy, its Goals, and every call escalated to it. | | [Fraud loss rate](/agents/operations#fraud-loss-rate) | Metric | Fraud loss rate is fraud and Dispute losses as a share of the revenue collected in the same month. | | [Fraud screen](/workflows/processes/trust-and-safety/fraud-screen) | Workflow | Fraud screen scores each new Customer for fraud and abuse and holds a suspect Party before its first money move. | | [Fraud screening](/systems/trust-and-governance/controls/fraud-screening) | Control | Each new Customer is scored for fraud, and a suspect Party is held before its first money move. | | [Free tools](/workflows/plays/free-tools) | Play | Free tools ship every read-only Verb with a one-field input as a no-signup tool, a citable Page and a free MCP tool. | | [French language](/systems/legal-and-corporate/floor/french-language) | Legal floor row | French language serves the Site, terms, and support in the French language wherever it is the sole official language, as prominent as any other. | | [Fully loaded acquisition cost](/agents/marketing#cac-fully-loaded) | Metric | Fully loaded acquisition cost is every Cost a Play posts, agent and shared Cost included, divided by the outside Customers it acquires. | | [Fully loaded Cost](/agents/finance#fully-loaded-cost) | Metric | Fully loaded Cost sums every Cost the Startup’s Actions post, plus its share of shared Cost under the stated allocation rule. | | [Function](/business/nouns/function) | Noun | A Function is how a Verb executes, as code, a generative model, an Agent, or a Human, invisible to the caller. | | [Functions](/code/platform/capabilities/functions) | Capability | Functions run a Verb as code, a model call, an agent or a human Task, behind one signature. | | [Fund offering](/systems/legal-and-corporate/floor/fund-offering) | Legal floor row | Fund offering shares fund material only privately unless every buyer is verified accredited, and files each required SEC notice on time. | | [Funnel](/business/nouns/funnel) | Noun | A Funnel is a designed path to an Offer: a landing Page, an opt-in that makes a Lead, a Sequence, then the Offer. | | [G2](/workflows/plays#g2) | Venue | G2 is a directory Venue. | | [Gambling](/systems/legal-and-corporate/floor/gambling) | Legal floor row | Gambling refuses any Startup that takes stakes on chance for a prize, including betting, paid-entry contests of chance, and casino games. | | [Gathering](/business/nouns/gathering) | Noun | A Gathering is a scheduled session many people attend at once, such as a webinar, a workshop, or a launch call, hosted by a Startup. | | [Gathering.register](/business/nouns/gathering/register) | Verb | Register gives a Contact a place at a Gathering, or a waitlist place when the Gathering is full. | | [Gemini](/workflows/plays#gemini) | Venue | Gemini is a search Venue. | | [GitHub](/workflows/plays#github) | Venue | GitHub is a community Venue. | | [Gmail](/workflows/plays#gmail) | Venue | Gmail is a email Venue. | | [Go dormant](/workflows/processes/go-dormant) | Process | Go dormant stops every running Workflow, ends Offers on their own terms, and keeps the records, Site, and domain until the Startup resumes. | | [Goal](/business/nouns/goal) | Noun | A Goal is what a Thing is trying to achieve: an objective with one or more Key Results. | | [Goals](/business/goals) | System | Goals records what each Thing is trying to achieve: its Goals, Key Results read from Metrics, and the Decisions behind them. | | [GoalTree](/code/ui/components/goal-tree) | Component | GoalTree draws Goals as a tree through the Goals each one supports, with every Key Result on pace or behind. | | [Google AI Overviews](/workflows/plays#google-ai-overviews) | Venue | Google AI Overviews is a search Venue. | | [Google Business Profile](/workflows/plays#google-business-profile) | Venue | Google Business Profile is a directory Venue. | | [Google Cloud Marketplace](/workflows/plays#google-cloud-marketplace) | Venue | Google Cloud Marketplace is a marketplace Venue. | | [Google Display](/workflows/plays#google-display) | Venue | Google Display is a display Venue. | | [Google Play](/workflows/plays#google-play) | Venue | Google Play is a app store Venue. | | [Google Search](/workflows/plays#google-search) | Venue | Google Search is a search Venue. | | [Governance](/systems/legal-and-corporate/floor/governance) | Legal floor row | Governance gives every board vote, consent, officer appointment, and officer signature the law requires to a natural person. | | [Governance oversight](/systems/trust-and-governance/controls/governance-oversight) | Control | The board or sole officer reviews control results each period and records that oversight as a Decision. | | [Graduate](/business/lifecycle/states/graduate) | Lifecycle state | Graduate is the state of a Startup that leaves its studio for a company of its own, keeping its Brand, Customers, and records. | | [Graduate](/workflows/processes/graduate) | Process | Graduate moves a Startup to a Company of its own: entity, Agreements, accounts, Audience, and records, with Customers served throughout. | | [Guard](/business/nouns/guard) | Noun | A Guard is a check every outbound Message and publish passes, from code rules to model review to a Human for high stakes. | | [Hacker News](/workflows/plays#hacker-news) | Venue | Hacker News is a community Venue. | | [Handle](/business/nouns/handle) | Noun | A Handle is an account or name a Startup or Brand holds on an outside platform, bound to an Integration credential. | | [Handle a takedown](/workflows/processes/takedowns/handle-takedown) | Workflow | Handle a takedown removes material named in a valid notice, tells the poster, and restores it after a valid counter-notice. | | [Handle a vulnerability report](/workflows/processes/vulnerability-disclosure/handle-vulnerability-report) | Workflow | Handle a vulnerability report acknowledges a security report within three days, confirms and fixes it, and credits the reporter. | | [Handle.connect](/business/nouns/handle/connect) | Verb | Connect binds a Handle to the Integration credential it publishes through, once the platform confirms the account. | | [Headless SaaS](/products/templates/headless-saas) | Product Template | Headless SaaS sells Software with no App of its own: Customers and their Agents use it through the API, MCP server, SDK, and CLI. | | [Health data](/systems/legal-and-corporate/floor/health-data) | Legal floor row | Health data requires a signed BAA before PHI flows, keeps PHI inside its Tenant, and gates consumer health data behind Consent. | | [Health data agreements](/systems/trust-and-governance/controls/health-data-agreements) | Control | A Startup holds health fields only after every upstream that processes them signs a business associate Agreement. | | [Hero](/code/ui/components/hero) | Component | Hero opens a Page with a headline, one supporting line, and one button bound to an Offer. | | [Hire a human](/workflows/processes/hiring/hire-human) | Workflow | Hire a human recruits a Person for a Role that the law or the Startup reserves for Humans, through a paid work trial. | | [Hiring](/workflows/processes/hiring) | Process | Hiring brings a Human into a Role through a paid work trial instead of interviewing. | | [Hiring](/systems/hiring) | System | Hiring fills open Roles with Humans: postings, candidates, screening calls held as Meetings, assessments and employment Agreements. | | [Hold](/business/lifecycle/states/hold) | Lifecycle state | Hold is the state of a Startup that keeps operating and serving Customers while its owner adds no new investment. | | [Hold review](/workflows/processes/hold-review) | Process | Hold review decides each quarter whether a Live Startup keeps its investment, holds, graduates, sells, or goes dormant. | | [Holder](/business/nouns/holder) | Noun | A Holder is the Party that holds a Share or an Instrument on a Company’s cap table. | | [House ads](/workflows/plays/house-ads) | Play | House ads show sibling Startups on the Portfolio’s own Sites, docs and receipts when relevance beats the host Page’s own conversion value. | | [Human](/business/nouns/human) | Noun | A Human is a Worker who is a person, acting on Tasks through Apps, Mailboxes, and Channels. | | [Human hours per $1k outside revenue](/agents/founding#human-hours) | Metric | Human hours per $1k outside revenue is the hours people log on the Startup per $1,000 of outside revenue, outside the legal floor. | | [Human.hold](/business/nouns/human/hold) | Verb | Hold sets aside part of a supplying Human’s earned balance against an open Dispute or an Order inside its clearance period. | | [Human.invite](/business/nouns/human/invite) | Verb | Invite asks a person to join a Startup in a named Role, sharing that Role’s work with its Agent. | | [Human.onboard](/business/nouns/human/onboard) | Verb | Onboard admits a recruited Human to supply work once their identity, Credentials and payout details verify. | | [Human.recruit](/business/nouns/human/recruit) | Verb | Recruit invites a person to supply credentialed work to a Startup through its supply App. | | [Human.release](/business/nouns/human/release) | Verb | Release frees a held amount for payout once its Dispute closes or its clearance period ends. | | [Human.remit](/business/nouns/human/remit) | Verb | Remit pays a supplying Human’s earned balance to their bank account through the Startup’s payment account. | | [Human.suspend](/business/nouns/human/suspend) | Verb | Suspend stops a supplying Human from taking new Tasks while a Credential lapses or a dispute is open. | | [Hypothesis](/business/nouns/hypothesis) | Noun | A Hypothesis is a belief about a Startup stated so it can be proved wrong, with the Metric and threshold that settle it. | | [Hypothesis.drop](/business/nouns/hypothesis/drop) | Verb | Drop retires a Hypothesis from active work and keeps it, with its Evidence, on record. | | [Hypothesis.test](/business/nouns/hypothesis/test) | Verb | Test binds a Hypothesis to the Experiment that decides it and moves the Hypothesis to testing. | | [ICP](/business/nouns/icp) | Noun | An ICP is the ideal customer profile a Startup is built to win: who they are and what they do. | | [Idea](/business/lifecycle/states/idea) | Lifecycle state | Idea is the state of a Startup that states its Idea and who pays, before any build work starts. | | [Idea](/business/nouns/idea) | Noun | An Idea is a business concept that exists apart from any Startup that pursues it and outlives each one. | | [Idea.pursue](/business/nouns/idea/pursue) | Verb | Pursue starts a Startup on an Idea as one variant of the Experiment that tests the Idea. | | [Identity](/code/platform/identity) | Capability | Identity signs in humans and agents, issues every key and session, and connects single sign-on and directory sync for Customers. | | [Identity checks](/systems/legal-and-corporate/floor/identity) | Legal floor row | Identity checks verify the natural person behind a Company, its beneficial owners, and representatives wherever KYC or a notary requires the person themselves. | | [Implementation](/business/nouns/implementation) | Noun | An Implementation is how an Interface, System, or Verb of a Product runs: managed by the platform, custom code on it, or external. | | [Import and export](/code/platform/import-export) | Capability | Import and export bring a Customer’s records in from another tool and hand every record back in one call. | | [Inbound sales](/workflows/processes/inbound-sales) | Process | Inbound sales answers every Lead in writing at once and carries the buyer to a signed Agreement. | | [Incident](/business/nouns/incident) | Noun | An Incident is an Issue where an Interface or Site fails Customers in production, tracked from detection to postmortem. | | [Incident handling](/systems/trust-and-governance/controls/incident-handling) | Control | Each Incident is contained, restored and closed with a postmortem and the Change that prevents a repeat. | | [Incident response](/workflows/processes/incident-response) | Process | Incident response restores service first, fixes the cause second, and prevents the repeat third. | | [Incident.acknowledge](/business/nouns/incident/acknowledge) | Verb | Acknowledge records that an on-call Worker owns an open Incident and stops its escalation. | | [Incident.open](/business/nouns/incident/open) | Verb | Open starts an Incident from a failing Monitor, an error spike or a Metric past its threshold, and pages the on-call Worker. | | [Incident.resolve](/business/nouns/incident/resolve) | Verb | Resolve closes an Incident once its Monitors pass, posts the resolution to the status page and opens the review Task. | | [Incorporation](/workflows/processes/incorporation) | Process | Incorporation forms the Startup’s own Company: the entity Decision, the certificate, a registered agent, the tax id, a bank account and founder shares. | | [Information returns](/systems/legal-and-corporate/floor/information-returns) | Legal floor row | Information returns collects a tax form and matches a TIN before a Company first pays a non-employee, then files each year’s returns. | | [Inherited floors](/systems/trust-and-governance/controls/inherited-floors) | Control | A namespace inherits every control Setting from its parent and can tighten it, never loosen it. | | [Input validation](/systems/trust-and-governance/controls/input-validation) | Control | Every Action’s inputs are checked against its Verb’s declared fields before it runs, and invalid input ends the Action refused. | | [Instagram](/workflows/plays#instagram) | Venue | Instagram is a social Venue. | | [Instrument](/business/nouns/instrument) | Noun | An Instrument is a right to future ownership in a Company: a SAFE, a note, an option or a warrant. | | [Instrument.cancel](/business/nouns/instrument/cancel) | Verb | Cancel ends an unvested, expired or forfeited Instrument and returns any option Shares to the pool. | | [Instrument.convert](/business/nouns/instrument/convert) | Verb | Convert turns a SAFE or note into Shares at a priced round, at its cap or discount, whichever gives more Shares. | | [Instrument.exercise](/business/nouns/instrument/exercise) | Verb | Exercise buys the Shares an option or warrant covers at its strike price, up to what has vested. | | [Instrument.grant](/business/nouns/instrument/grant) | Verb | Grant gives a Holder an option from the pool, with its strike price, vesting schedule and cliff. | | [Insurance applications](/systems/legal-and-corporate/floor/insurance-applications) | Legal floor row | Insurance applications have an officer sign every representation on an application, since a misstatement can void the policy. | | [Insurance producers](/systems/legal-and-corporate/floor/insurance-producers) | Legal floor row | Insurance producers sells, quotes, or negotiates insurance only through a producer licensed in the buyer’s state, and pays commission only to licensees. | | [Intakes answered on time](/agents/legal#intakes-on-time) | Metric | Intakes answered on time is the share of intake Threads that get a first answer before their deadline. | | [Integration](/business/nouns/integration) | Noun | An Integration is an outside Source connected to a System with credentials, at Studio, Startup, or Customer scope. | | [Integration Engineer](/agents/engineering/integration-engineer) | Role | The Integration Engineer connects each Startup to its providers and imports, and keeps every sync healthy. | | [Integration partners](/workflows/plays/integration-partners) | Play | Integration partners ship an integration with a product the Customer already uses, then list it and share Leads under a referral Agreement. | | [Integration.call](/business/nouns/integration/call) | Verb | Call sends one request to an upstream through an Integration, with its token filled in server-side, for endpoints no Mapping covers. | | [Integration.connect](/business/nouns/integration/connect) | Verb | Connect asks an account holder to approve an outside account for one System and records the grants they approve. | | [Integration.pause](/business/nouns/integration/pause) | Verb | Pause stops every call through an Integration at once and keeps its token and cursor. | | [Integration.reconnect](/business/nouns/integration/reconnect) | Verb | Reconnect re-approves an Integration in place, keeping its id and cursor, so nothing re-imports. | | [Integration.refresh](/business/nouns/integration/refresh) | Verb | Refresh renews an Integration’s outside token before it expires; a refused refresh moves it to `needsReauth`. | | [Integration.resume](/business/nouns/integration/resume) | Verb | Resume restarts a paused Integration from its cursor and releases the Actions that waited on it. | | [Integration.revoke](/business/nouns/integration/revoke) | Verb | Revoke ends an Integration at once: its token is revoked with the upstream, and every record it brought in stays. | | [Integration.sync](/business/nouns/integration/sync) | Verb | Sync exchanges records between a System and its connector, and the declared leader wins every conflict. | | [Integrations](/code/platform/integrations) | Capability | Integrations bind a wrapped outside Source to a System with credentials under an Agreement. | | [Intellectual property](/systems/intellectual-property) | System | Intellectual property keeps a Startup’s trademarks, patents, Domains and handles as one register, with deadlines and renewals watched. | | [Interface](/business/nouns/interface) | Noun | An Interface is how a person or an Agent reaches a Product: an API, MCP server, CLI, SDK, Site, or App. | | [Interview](/business/nouns/interview) | Noun | An Interview is one person’s pass through a question script, led by an Agent, whose answers become Evidence. | | [Investment advisers](/systems/legal-and-corporate/floor/investment-advisers) | Legal floor row | Investment advisers sells personal securities advice only through a registered adviser; a Startup itself publishes general information only. | | [Invoice](/business/nouns/invoice) | Noun | An Invoice is what a Customer owes for one or more Offers over one billing period. | | [Invoice reminders](/workflows/processes/billing/invoice-reminders) | Workflow | Invoice reminders tell each Customer about a `send` Invoice before its due date and once past it, and never retry a charge. | | [Invoice.bill](/business/nouns/invoice/bill) | Verb | Bill finalizes an Invoice and presents it to the Customer for payment. | | [Invoice.collect](/business/nouns/invoice/collect) | Verb | Collect charges a Customer’s saved payment method for an open Invoice and retries on failure. | | [Invoice.refund](/business/nouns/invoice/refund) | Verb | Refund returns all or part of a paid Invoice to the Customer’s original payment method and posts the reversing Entries. | | [Invoice.void](/business/nouns/invoice/void) | Verb | Void cancels an unpaid Invoice, keeps it on record, and posts the reversing Entries. | | [InvoiceList](/code/ui/components/invoice-list) | Component | InvoiceList lists one Customer’s Invoices newest first, each with its status, its PDF and a pay button while it is open. | | [Invoicing](/systems/finance/invoicing) | Capability | Invoicing bills a Customer with a numbered Invoice, payment terms and a hosted payment page, then collects, reminds or voids it. | | [Issue](/business/nouns/issue) | Noun | An Issue is a Task reporting a problem or request, such as a bug or a feature request, with a reporter and a triage step. | | [Issue a refund](/workflows/processes/billing/issue-refund) | Workflow | Issue a refund returns money within the Billing Specialist’s Limit and leaves an Approval for any amount above it. | | [Issue.estimate](/business/nouns/issue/estimate) | Verb | Estimate records the effort an Issue needs, in days, so a week holds only what fits. | | [Issue.reopen](/business/nouns/issue/reopen) | Verb | Reopen returns a resolved Issue to its owning Role when the fix does not hold. | | [Issue.resolve](/business/nouns/issue/resolve) | Verb | Resolve closes an Issue with its fix recorded and tells every Customer who reported it. | | [Issue.schedule](/business/nouns/issue/schedule) | Verb | Schedule commits an Issue to a week of work and records each scope change after the week starts. | | [Issue.triage](/business/nouns/issue/triage) | Verb | Triage sets an Issue’s severity and owning Role from its content and the Customer it affects. | | [Iteration](/workflows/processes/iteration) | Process | Iteration improves the Startup one change at a time: one number, the worst step, and one change a week. | | [Jurisdictions](/systems/legal-and-corporate/floor/jurisdictions) | Legal floor row | Jurisdictions governs a first cold email outside the US: sent under legitimate interest with its source named, or skipped where Consent is required. | | [Key Result](/business/nouns/key-result) | Noun | A Key Result is one measurable target inside a Goal: a Metric, a baseline, a target, and a deadline. | | [Keyless signup](/workflows/customer/plays/keyless-signup) | Play | Keyless signup lets an Agent call and pay on first contact, with no key and no signup, through a priced payment-required reply. | | [KeyResult](/code/ui/components/key-result) | Component | KeyResult shows one Key Result's value against its target, with a weekly pace derived from the distance and weeks left. | | [Keyword](/business/nouns/keyword) | Noun | A Keyword is a search phrase or AI prompt that Pages target, with its rank and citations observed over time. | | [Keyword.measure](/business/nouns/keyword/measure) | Verb | Measure records a Keyword’s monthly search volume, difficulty, cost per click and trend in one locale. | | [Knowledge base](/systems/knowledge-base) | System | Knowledge base holds the articles Customers and Agents answer from, in a searchable help center that cites every answer. | | [KV and cache](/code/platform/kv-cache) | Capability | KV and cache serve hot reads at the edge with explicit expiry, and every value rebuilds from the database. | | [Launch announcement](/workflows/processes/launches/launch-announcement) | Workflow | Launch announcement tells a new Startup’s Audiences it is live through a launch post, its listings, and Agent registries. | | [Launch sites](/workflows/plays/launch-sites) | Play | Launch sites post a one-day launch that buys a dated record and a backlink, by default as one collection launch per template. | | [Launch week](/workflows/plays/launch-week) | Play | Launch week batches a quarter’s tier 1 and tier 2 Changes into five dated days of posts, Pages, listing refreshes and newsletters. | | [Launches](/workflows/processes/launches) | Process | Launches tell the right Audiences a Startup is live, where those Audiences already look. | | [Lawful basis](/systems/trust-and-governance/controls/lawful-basis) | Control | Personal data is processed only under a recorded Consent or another lawful basis tied to a Purpose. | | [Lawyers](/systems/legal-and-corporate/floor/lawyers) | Legal floor row | Lawyers applies the conduct rules wherever a lawyer’s services are sold: no outcome promises, no paid recommendations, no fee-sharing, and conflict checks. | | [Lead](/business/nouns/lead) | Noun | A Lead is a Contact who raised a hand, by joining a Waitlist, filling a Form, or replying, without accepting an Offer. | | [Lead nurture](/workflows/plays/lead-nurture) | Play | Lead nurture enrolls each Lead who has not bought in a Sequence keyed to what they do, ending at purchase, reply or 90 silent days. | | [Lead.assign](/business/nouns/lead/assign) | Verb | Assign gives a Lead one owner Worker, by round robin, territory or ICP fit, as the Startup’s routing Policy says. | | [Lead.convert](/business/nouns/lead/convert) | Verb | Convert ends a qualified Lead’s pursuit as a Lead: it opens a Deal or routes the Lead to self-serve checkout. | | [Lead.disqualify](/business/nouns/lead/disqualify) | Verb | Disqualify ends a Lead’s pursuit because it fits no Offer, with the reason; its Contact record and Consent stay. | | [Lead.nurture](/business/nouns/lead/nurture) | Verb | Nurture takes a Lead that is not ready to buy off its owner’s queue and onto a Sequence, until it raises a hand again. | | [Lead.qualify](/business/nouns/lead/qualify) | Verb | Qualify confirms a Lead matches an Offer’s ICP and opens a Deal for it. | | [Ledger](/systems/ledger) | System | Ledger is the double-entry book of record: Entries posted from Events, reconciled to Transactions, and closed each Period into statements. | | [Legal Lead](/agents/legal/legal-lead) | Role | The Legal Lead keeps the Startup’s terms, privacy notice, and Consent rules current and routes every Reserved Act to a licensed Human. | | [Legal notices](/workflows/processes/legal-notices) | Process | Legal notices routes subpoenas, summonses, demand letters, and regulator inquiries to the owner of record within a day, and holds the records they name. | | [Legal process](/systems/legal-and-corporate/floor/legal-process) | Legal floor row | Legal process answers a subpoena, summons, or court order by its deadline through the owner of record, and holds every record it names. | | [Legal services](/systems/integrations/upstreams#legal-services) | Capability | Legal services draft, review and advise, with every Reserved Act performed by an independent licensed attorney. | | [Legal Team](/agents/legal) | Team | The Legal Team keeps the Startup lawful: Agreements, privacy and Consent from day one, screening of every Offer, and every Reserved Act. | | [LensGrid](/code/ui/components/lens-grid) | Component | LensGrid places Things on a stored two-by-two grid of two Metrics, as one part of a Dashboard. | | [License renewals](/workflows/processes/license-renewals) | Process | License renewals renews each business license and permit before it expires and holds any Offer that depends on one that lapses. | | [Licensed acts](/systems/legal-and-corporate/floor/licensed-acts) | Legal floor row | Licensed acts stops an Order’s work at every Reserved Act until a credentialed Human in standing signs it as an Attestation. | | [Licensed professional network](/start/templates/licensed-network) | Startup Template | A Licensed professional network extends the Founder-led marketplace into a Licensed-human marketplace that buyers and their Agents book. | | [Licensed review](/systems/integrations/upstreams#licensed-review) | Capability | Licensed review has a credential holder review agent-prepared work and approve, return or decline it under their own Credential. | | [Licensed review](/workflows/processes/licensed-review) | Process | Licensed review puts a credentialed Human’s Attestation on every Reserved Act before it reaches a Customer. | | [Licensed-human marketplace](/products/templates/licensed-marketplace) | Product Template | A Licensed-human marketplace matches buyers with credentialed professionals and adds recruiting, Credential checks, and an App where they take work. | | [Licenses and permits](/systems/legal-and-corporate/licenses-and-permits) | Capability | Licenses and permits obtain and renew the business licenses and regulated authorities the Company needs where it operates. | | [Licensing](/systems/legal-and-corporate/floor/licensing) | Legal floor row | Licensing holds an Offer from sale until every Credential, registration, or entity of record it needs is held and counsel has read it. | | [Lifecycle](/business/nouns/lifecycle) | Noun | A Lifecycle is the states a Thing of one Noun moves through and the Verbs that move it between them. | | [Lifetime value](/agents/finance#ltv) | Metric | Lifetime value is the contribution an outside Customer is expected to produce, capped at 24 months. | | [Limit](/business/nouns/limit) | Noun | A Limit is a bound on a Permission, Entitlement, or Mandate, checked before every call; exceeding it creates an Approval. | | [Limit.raise](/business/nouns/limit/raise) | Verb | Raise lifts a Limit after an Approval allows it, and the Action that waited on it proceeds. | | [LinkedIn](/workflows/plays#linkedin) | Venue | LinkedIn is a professional Venue. | | [LinkedIn outbound](/workflows/plays/linkedin-outbound) | Play | LinkedIn outbound sends connection requests and Messages from a Human’s own LinkedIn profile under a Mandate, with Agents researching and drafting. | | [Liquidity](/agents/operations#liquidity) | Metric | Liquidity is the share of listings that transact with an outside Customer within the window. | | [Listings](/systems/listings) | System | Listings presents other Parties in a public Collection: unclaimed profiles, claims, verification, paid placement and moderation. | | [Live](/business/lifecycle/states/live) | Lifecycle state | Live is the state of a Startup that is publicly reachable and takes money from Customers for at least one Offer. | | [Localization](/systems/marketing/localization) | Capability | Localization translates a Startup’s Site, docs, Messages, and support into each Market’s locales and keeps every translation in step with its source. | | [Log completeness](/systems/trust-and-governance/controls/log-completeness) | Control | Every Event commits to the previous Event’s hash, and hourly published roots let anyone prove the log complete. | | [Logo churn](/agents/customer#logo-churn) | Metric | Logo churn is the share of outside Customers paying at the start of a month who stop paying by its end. | | [Made with](/workflows/plays/made-with) | Play | Made with puts a disclosed, coded line naming the Startup’s Brand on every output a Customer sends to someone who is not one. | | [Mail handling](/workflows/processes/mail-handling) | Process | Mail handling reads every scanned piece of mail at the Startup’s address, routes legal mail within the hour, deposits checks and forwards the rest. | | [Mailbox](/business/nouns/mailbox) | Noun | A Mailbox is an email Channel at a Domain, held by a Startup, a Role, or a Worker, so every Agent has its own. | | [Mailbox.rest](/business/nouns/mailbox/rest) | Verb | Rest pauses a Mailbox’s sending when a brake fires and resumes it when the reading clears. | | [Mailbox.retire](/business/nouns/mailbox/retire) | Verb | Retire stops a Mailbox for good and keeps its address, Messages and sending history. | | [Mailbox.warm](/business/nouns/mailbox/warm) | Verb | Warm ramps a new Mailbox from a few sends a day to its cap over two to four weeks. | | [Mailboxes](/systems/mailboxes) | System | Mailboxes sends and receives Messages from addresses at a Startup’s Domains, held by a Startup, a Role or a Worker, with Consent and Suppressions enforced. | | [Mailing address](/systems/legal-and-corporate/business-address) | Capability | Mailing address gives a Startup a postal address that receives its mail, scans each piece, and forwards it or deposits checks. | | [Make](/workflows/plays#make) | Venue | Make is a marketplace Venue. | | [Managed service firm](/start/templates/managed-service-firm) | Startup Template | A Managed service firm extends the Agent-run services firm with Humans who share Roles and an E2E managed service for businesses. | | [Mandate](/business/nouns/mandate) | Noun | A Mandate is a standing authorization for an Agent to act for a Party, within Permissions and Limits, until it expires. | | [Mandate.authorize](/business/nouns/mandate/authorize) | Verb | Authorize grants an Agent a standing Mandate to perform a Verb within a Limit, without asking each time. | | [Mandate.pause](/business/nouns/mandate/pause) | Verb | Pause stops every new Action under a Mandate at once and keeps its scope, so it can resume unchanged. | | [Mandate.resume](/business/nouns/mandate/resume) | Verb | Resume restarts a paused Mandate with its scope, Limits and approval rule unchanged. | | [Mandate.revoke](/business/nouns/mandate/revoke) | Verb | Revoke ends a Mandate at once, so new Actions under it are refused and running ones finish. | | [Mandate.spend](/business/nouns/mandate/spend) | Verb | Spend pays an outside party for a Startup with a single-use card, within a Mandate and its Limit. | | [Manual Entry review](/systems/trust-and-governance/controls/manual-entry-review) | Control | An Entry no Verb caused lands only after a second Role approves it. | | [Mapping](/business/nouns/mapping) | Noun | A Mapping translates one Source’s shape into the registry’s: its fields to a Noun’s fields, or an outside endpoint’s inputs and outputs to a Verb’s. | | [Market](/business/nouns/market) | Noun | A Market is a region where a Startup sells, hires, or keeps books, with its currency, locales, and the floor rows that wake there. | | [Market data](/systems/marketing/market-data) | Capability | Market data measures the outside market: search demand, rankings, links, answer citations, running ads and social reach, each with provenance. | | [Market.enter](/business/nouns/market/enter) | Verb | Enter opens a Market to a Startup: Prices in its currency, the Site in its locales, and its floor rows woken. | | [Marketing Lead](/agents/marketing/marketing-lead) | Role | The Marketing Lead owns demand and the story: positioning in the buyer’s words, launches, and the demand Plays each Startup runs. | | [Marketing Team](/agents/marketing) | Team | The Marketing Team creates and harvests demand: the Brand story, launches, Content, Experiments, and the Metrics the whole Startup reads. | | [Marketplace](/products/templates/marketplace) | Product Template | A Marketplace matches buyers with Suppliers who deal with each other directly, and earns a take rate on every transaction it settles. | | [Marketplace listings](/workflows/plays/marketplace-listings) | Play | Marketplace listings put a Product in app stores and cloud marketplaces and request reviews only after a Customer’s first success. | | [Marketplace payments](/systems/finance/marketplace-payments) | Capability | Marketplace payments settle each sale on the Supplier’s own connected Stripe account and keep the Marketplace’s take as an application fee. | | [Matchmaking](/systems/matching) | System | Matchmaking pairs buyers with Suppliers’ Offers, records the merchant of record on each Order, and takes the Startup’s fee through Stripe. | | [MCP](/code/mcp/reference) | Interface | The MCP server gives any agent four tools, `search`, `fetch`, `try` and `do`, that reach every Verb through typed programs. | | [MCP Registry](/workflows/plays#mcp-registry) | Venue | MCP Registry is a agent registry Venue. | | [Media](/systems/marketing/media) | Capability | Media generates, edits and transcribes images, video, voice and music, with provenance on every asset. | | [Media production](/systems/media) | System | Media production makes a Startup’s Videos, images and voice from its records: drafted, generated, rendered per format, checked, then finalized for publishing. | | [Meeting](/business/nouns/meeting) | Noun | A Meeting is a scheduled time when Workers and Contacts meet about one or more Things, producing notes, Decisions, and Tasks. | | [Meeting.book](/business/nouns/meeting/book) | Verb | Book schedules a Meeting with a Contact at a time both calendars hold free. | | [Member Directory](/business/nouns/member-directory) | Noun | A Member Directory is a Customer’s own list of people and groups, pushed into its Tenant so access follows employment. | | [MemberDirectory.deactivate](/business/nouns/member-directory/deactivate) | Verb | Deactivate stops a Member Directory’s pushes; everyone it added keeps their Roles until an admin removes them. | | [MemberDirectory.deprovision](/business/nouns/member-directory/deprovision) | Verb | Deprovision ends one person’s access to a Tenant in one Action when the Customer’s directory removes them. | | [MemberDirectory.provision](/business/nouns/member-directory/provision) | Verb | Provision starts a Customer’s Member Directory pushing people and groups into its Tenant, with groups mapped to Roles. | | [Memory](/business/nouns/memory) | Noun | A Memory is a Worker’s own Collection of what it has learned and kept, read by its Functions. | | [Merchant account](/systems/finance/merchant-account) | Capability | Merchant account gives a Startup its own connected payments account at its first sale, so it sells and settles as seller of record. | | [Message](/business/nouns/message) | Noun | A Message is one communication from any party over one medium, such as email, SMS, or chat, inbound or outbound. | | [Message.broadcast](/business/nouns/message/broadcast) | Verb | Broadcast sends one Message to an Audience, now or at a set time, split by Variant when an Experiment runs. | | [Message.schedule](/business/nouns/message/schedule) | Verb | Schedule holds a Message until a set time and sends it then, unless it is canceled first. | | [Meter](/business/nouns/meter) | Noun | A Meter is a billable measure of usage that turns usage Events into Entries exactly once. | | [Metric](/business/nouns/metric) | Noun | A Metric is a named measure computed from Events or Entries, always derived and never typed in. | | [Metric freshness](/agents/marketing#metric-freshness) | Metric | Metric freshness is the share of Metrics whose latest value is less than one day old. | | [Metric.define](/business/nouns/metric/define) | Verb | Define compiles a Metric’s query against the Startup’s Events and Entries and lists every Event it reads. | | [Metric.query](/business/nouns/metric/query) | Verb | Query reads Metrics or Events as a trend, funnel, retention curve, path or lifecycle, broken down by any property. | | [Metric.watch](/business/nouns/metric/watch) | Verb | Watch alerts the owner of a Metric when it crosses a threshold, by a Task or a Message. | | [MetricTile](/code/ui/components/metric-tile) | Component | MetricTile shows one Metric's value for a window, with its trend, its noise band, and how fresh the number is. | | [Minimum Success Criteria](/business/nouns/minimum-success-criteria) | Noun | Minimum Success Criteria is the one number a Startup must reach by a date to stay worth running: a Goal the Founder sets once. | | [Minors](/systems/legal-and-corporate/floor/minors) | Legal floor row | Minors gets verifiable parental Consent before collecting personal data from a child under 13, and age-gates every Product not built for children. | | [Mode](/business/nouns/mode) | Noun | A Mode is how a caller invokes a Verb: try waits and stores nothing, send returns a pending Action, do waits for the result. | | [Monday Role review](/workflows/processes/role-review/monday-role-review) | Workflow | Monday Role review records a Role Review for every filled Role and sends the Founder one Decision request per missed result. | | [Money services](/systems/legal-and-corporate/floor/money-services) | Legal floor row | Money services moves funds only through the payments rail; a Startup that transmits money, issues stored value, or lends needs a licensed upstream. | | [Monitor](/business/nouns/monitor) | Noun | A Monitor is a scheduled check on something outside a Startup’s control, such as uptime, a Keyword’s rank or an AI answer, recording Events. | | [Monitor.check](/business/nouns/monitor/check) | Verb | Check runs a Monitor once now from several regions and records the result as an Event. | | [Monitoring](/code/systems/monitoring) | System | Monitoring captures errors, logs and traces, checks uptime and scheduled jobs, and ties each failure to the Version that caused it. | | [Month-3 retention](/agents/customer#month-3-retention) | Metric | Month-3 retention is the share of outside Customers who first paid in one month and still pay three months later. | | [Monthly budget](/workflows/processes/budget/monthly-budget) | Workflow | Monthly budget compares last month’s spend with each Budget, forecasts six months ahead, and asks the Founder to approve any Budget change. | | [Monthly close](/workflows/processes/books/monthly-close) | Workflow | Monthly close reconciles every Transaction to the ledger and closes the Period by the set working day. | | [Motion](/business/nouns/motion) | Noun | A Motion is the shape of a sale: who buys an Offer and who acts for them, such as b2b, b2c, b2d, b2a, or b2a2b. | | [Motor records](/systems/legal-and-corporate/floor/motor-records) | Legal floor row | Motor records serves personal fields from a state motor vehicle record only for a declared permissible use, recording every recipient and use. | | [Multi-human](/agents/operating-models/multi-human) | Operating model | Multi-human is the operating model where several Humans share Roles with Agents, each Human working under their own Mandate and Limits. | | [Must-have share](/agents/product#must-have-share) | Metric | Must-have share is the share of surveyed activated outside Customers who say losing the Product would disappoint them most. | | [n8n](/workflows/plays#n8n) | Venue | n8n is a marketplace Venue. | | [Namespace isolation](/systems/trust-and-governance/controls/namespace-isolation) | Control | A namespace reads and writes only its own records, unless an Agreement grants a scoped read. | | [Navigation](/code/ui/components/navigation) | Component | Navigation lists the routes one Persona may reach in an App or Site, derived from its grants. | | [Net revenue retention](/agents/customer#net-revenue-retention) | Metric | Net revenue retention is this month’s revenue from outside Customers who paid twelve months ago, divided by their revenue then. | | [Next outcome](/workflows/customer/plays/next-outcome) | Play | Next outcome offers the next Service a Customer needs at the moment it comes due, such as an annual filing after a formation. | | [Nightly quality run](/code/verification/nightly-quality-run) | Workflow | Nightly quality run re-runs every check, replays known-good runs, and opens an Issue for each regression. | | [Notarization](/systems/legal-and-corporate/notarization) | Capability | Notarization has a commissioned notary notarize a signer’s Document online and returns the certificate and journal entry as records. | | [Notices](/systems/legal-and-corporate/floor/notices) | Legal floor row | Notices publishes a privacy notice and terms on every Site before its first signup or card, rendered from the Startup’s definition. | | [Notices](/systems/notices) | System | Notices delivers in-app, push, SMS and email notices to Customers and Workers by their preferences, with digests and quiet hours. | | [Notify a breach](/workflows/processes/notify-regulator/notify-breach) | Workflow | Notify a breach tells each regulator and affected Person about a personal-data breach within the legal deadline, which counts from awareness. | | [Notify regulator](/workflows/processes/notify-regulator) | Process | Notify regulator files every notice a notifiable Incident owes before its statutory clock runs out, and records each filing. | | [Noun](/business/nouns/noun) | Noun | A Noun is a type of record, with its properties, its relationships, and the Verbs that act on it. | | [Noun.retire](/business/nouns/noun/retire) | Verb | Retire removes a published Noun from new Versions; its records, its history and every pinned Version keep serving. | | [Noun.trace](/business/nouns/noun/trace) | Verb | Trace lists every Verb, Process, Offer, Dashboard and Version that references a Noun, so an edit or a retire shows its reach first. | | [npm](/workflows/plays#npm) | Venue | npm is a directory Venue. | | [Observability](/code/platform/observability) | Capability | Observability captures logs, traces and errors from every request and Action, and opens an Incident when a check fails. | | [Offboard from a Role](/workflows/processes/staffing/offboard-from-role) | Workflow | Offboard from a Role revokes the leaving holder’s access within the hour, hands on their open work, and settles what they are owed. | | [Offer](/business/nouns/offer) | Noun | An Offer is a Product, under a Brand, at a price, on terms, made by a Startup. | | [Offer.accept](/business/nouns/offer/accept) | Verb | Accept records that a party takes an Offer, which makes that party a Customer of the Startup. | | [Offer.grant](/business/nouns/offer/grant) | Verb | Grant adds an Entitlement to an Offer: a Verb its Customers may call, optionally bounded by a Limit. | | [Offer.publish](/business/nouns/offer/publish) | Verb | Publish makes an Offer available for parties to accept. | | [Offer.subscribe](/business/nouns/offer/subscribe) | Verb | Subscribe accepts a recurring Offer as a Subscription that renews each period until it ends. | | [Offer.trial](/business/nouns/offer/trial) | Verb | Trial starts a Customer on an Offer free for a set number of days, with or without a card, converting or ending by its terms. | | [Offer.withdraw](/business/nouns/offer/withdraw) | Verb | Withdraw closes a published Offer to new Customers and leaves every existing Order and Subscription in force. | | Offline replay | Test ladder rung | Offline replay scores a Variant on the kept log of past choices before anyone sees it. | | [On-demand work](/systems/integrations/upstreams#on-demand-work) | Capability | On-demand work books vetted, credentialed people per shift or job and pays them on verified completion. | | [Onboard a Customer](/workflows/processes/onboarding/onboard-customer) | Workflow | Onboard a Customer gets each new signup to first value, doing the setup by hand until three repeats make it an Issue. | | [Onboard into a Role](/workflows/processes/staffing/onboard-into-role) | Workflow | Onboard into a Role grants the new holder only the Permissions the seat needs, hands them its contract, and sets the first Role review. | | [Onboarding](/workflows/processes/onboarding) | Process | Onboarding gets every new Customer to first value, by hand until the Startup automates each step. | | [Onboarding Specialist](/agents/customer/onboarding-specialist) | Role | The Onboarding Specialist gets each new Customer to first value, doing the setup by hand until the Startup automates it. | | [One-way Action windows](/systems/trust-and-governance/controls/one-way-windows) | Control | A one-way Action waits out its delay window, and an Action over its Limit waits for an Approval. | | [Open source](/workflows/plays/open-source) | Play | Open source publishes the SDK and integration layer as open repositories, keeps the hosted Product paid, and answers every issue within 48 hours. | | [Opening](/business/nouns/opening) | Noun | An Opening is a Startup’s computed need for a Human in a Role: its kind, its reason, and the Hypothesis a hire must prove. | | [Operations Lead](/agents/operations/operations-lead) | Role | The Operations Lead runs the Startup’s week: it runs the Monday Role review, coordinates incidents, and requests Decisions from the Founder. | | [Operations Team](/agents/operations) | Team | The Operations Team runs the Startup day to day: it delivers outcomes, keeps human supply booked, stops abuse, and runs the Monday Role review. | | Opinion | Evidence grade | Opinion is an Evidence grade: what outside people think, which weighs zero. | | [Order](/business/nouns/order) | Noun | An Order is a Customer’s commitment to buy one or more Offers once, moving from placed to paid, fulfilled, and closed. | | [Order.cancel](/business/nouns/order/cancel) | Verb | Cancel ends an Order before fulfillment and returns any payment in full. | | [Order.confirm](/business/nouns/order/confirm) | Verb | Confirm records the Customer’s sign-off on delivered work, which closes the Order and earns the Startup its fee. | | [Order.deliver](/business/nouns/order/deliver) | Verb | Deliver hands the finished work of a Service Order to its Customer and opens the acceptance window. | | [Order.dispute](/business/nouns/order/dispute) | Verb | Dispute contests a delivered Order under its Outcome Contract and starts the remedy the contract names. | | [Order.fulfill](/business/nouns/order/fulfill) | Verb | Fulfill grants what an Order bought: Entitlements for software and data, a shipment for goods. | | [Order.pay](/business/nouns/order/pay) | Verb | Pay settles an Order’s amount through the Startup’s payment account and posts the matching Entries. | | [Order.place](/business/nouns/order/place) | Verb | Place commits a Customer to buy an Offer once and records the Offer Version and price at that moment. | | [Order.refund](/business/nouns/order/refund) | Verb | Refund returns all or part of an Order’s payment to the Customer and posts the reversing Entries. | | [Order.revise](/business/nouns/order/revise) | Verb | Revise sends delivered lines back for one counted revision, with the changes the Customer asks for. | | [Order.screen](/business/nouns/order/screen) | Verb | Screen scores an Order’s payment before it is charged and allows, authenticates, holds or blocks it by the Startup’s risk Policy. | | [Order.start](/business/nouns/order/start) | Verb | Start checks a Service Order’s inputs against its brief, then moves it from intake to working and starts its deadline. | | [Organic share](/agents/marketing#organic-share) | Metric | Organic share is the share of new outside Customers whose first touch was not paid. | | [Organic social](/workflows/plays/organic-social) | Play | Organic social turns facts and artifacts a Startup already has into posts from its disclosed agent accounts and the Studio’s shared accounts. | | [Organic visits](/agents/marketing#organic-visits) | Metric | Organic visits counts the Visits a Startup’s Pages get each week from unpaid search and answer engines. | | [Organization](/business/nouns/organization) | Noun | An Organization is an outside party as one Startup knows it, keyed by its domain, such as an employer or a vendor. | | [Organization.merge](/business/nouns/organization/merge) | Verb | Merge joins a duplicate Organization into another, keeping every Contact, Deal and Event on the one that remains. | | [Outbound](/workflows/processes/outbound) | Process | Outbound reaches Prospects who match the ICP, with a legal basis for contact and within the touch Limit. | | [Outbound calling](/workflows/plays/outbound-calling) | Play | Outbound calling phones local and small Organizations, using a voice Agent only where Consent is recorded and a Human where law requires one. | | [Outbound sequence](/workflows/processes/outbound/outbound-sequence) | Workflow | Outbound sequence reaches Prospects who match the ICP, honoring every Suppression, and routes every reply. | | [Outcome confirmation](/systems/trust-and-governance/controls/outcome-confirmation) | Control | Every Order’s outcome is confirmed before it is billed, and a missed outcome is redone once. | | [Outcome Contract](/business/nouns/outcome-contract) | Noun | An Outcome Contract is the terms on an Offer that warrant a Service’s result: done, acceptance, assurance, remedy, and earnings. | | [Outlook](/workflows/plays#outlook) | Venue | Outlook is a email Venue. | | [Outside accounts](/systems/finance/outside-accounts) | Capability | Outside accounts register the Company on platforms that verify businesses: app stores, ad networks, marketplaces and directories. | | [Outside paid Orders](/agents/sales#outside-paid-orders) | Metric | Outside paid Orders counts paid Orders from outside Customers in the window, net of refunds. | | [Outside paying Customers](/agents/founding#outside-paying-customers) | Metric | Outside paying Customers counts distinct outside Customers with at least one paid, unrefunded Order in the window. | | [Outside revenue](/agents/founding#outside-revenue) | Metric | Outside revenue is revenue from Customers who share no owner, Studio account, Agreement or sibling chain with the Startup. | | [Owned following](/workflows/plays/owned-following) | Play | Owned following grows a niche newsletter, community and shared accounts in a Studio media Startup and lends its slots to siblings by expected value. | | [Owned newsletter](/workflows/plays/owned-newsletter) | Play | Owned newsletter grows a subscribed list with one fact and one Offer per issue, and suppresses subscribers silent for 90 days. | | [Page](/business/nouns/page) | Noun | A Page is an addressable page of a Site, of a named type such as pricing, about one Thing or each member of a Collection. | | [Page task success](/agents/product#page-task-success) | Metric | Page task success is the share of tested Visitors who finish a Page’s main task on the first try. | | [Paid listing conversion](/agents/sales#paid-listing-conversion) | Metric | Paid listing conversion is the share of claimed listings that pay for placement within the window. | | [Paid Media Manager](/agents/marketing/paid-media-manager) | Role | The Paid Media Manager runs paid Plays: bids and budgets per venue, creative rotation, ad policy, and conversions sent back to each venue. | | [Paid pilot](/workflows/sales/plays/paid-pilot) | Play | Paid pilot runs the Product on a buyer’s own sample in a sandbox and sets success criteria from the numbers the buyer saw. | | Paid probe | Test ladder rung | Paid probe spends $100 on one ad venue to measure what a click and a Customer cost. | | [Paid search](/workflows/plays/paid-search) | Play | Paid search bids on Keywords that state intent and runs only while the first transaction’s margin exceeds its cost per first transaction. | | [Paid social](/workflows/plays/paid-social) | Play | Paid social runs Ads targeted by Audience instead of query, first as a pooled test and at scale only for messages that already won. | | [Partner](/business/nouns/partner) | Noun | A Partner is an outside Organization that is party to an Agreement with a Startup, supplying it, distributing its Offers, or both. | | [Partner Manager](/agents/sales/partner-manager) | Role | The Partner Manager signs and serves the outside Organizations that resell, refer, or integrate the Startup’s Products. | | [Partner-sourced revenue](/agents/sales#partner-sourced-revenue) | Metric | Partner-sourced revenue is the revenue each month from Customers a Partner referred. | | [Party](/business/nouns/party) | Noun | A Party is a person or legal entity that can be a side of an Agreement or an Order, or hold rights. | | [Party screening](/systems/legal-and-corporate/party-screening) | Capability | Party screening checks who a counterparty is and whether a Startup may deal with them, from identity to sanctions and fraud signals. | | [Party.screen](/business/nouns/party/screen) | Verb | Screen checks a Party against official registers and restricted-party lists and keeps the result as a Screening. | | [Patent filings](/systems/legal-and-corporate/patents) | Capability | Patent filings file provisional and full applications for the Company’s inventions, naming human inventors, and keep each one maintained. | | [Pay accuracy](/agents/people#pay-accuracy) | Metric | Pay accuracy is the share of pay runs that need no correction afterwards. | | [Pay bills](/workflows/processes/payables/pay-bills) | Workflow | Pay bills matches a new Bill to its Agreement, approves it within a Mandate, pays it on its due date and reconciles the payment. | | [Pay people](/workflows/processes/payroll/pay-people) | Workflow | Pay people pays every employee and contractor for the Period, with withholding and tax statements. | | [Pay Run](/business/nouns/pay-run) | Noun | A Pay Run is one pay period’s payroll for a Company: each employee’s gross pay, withholding, deductions and net pay, approved and paid together. | | [Pay runs](/systems/payroll) | System | Pay runs keeps each employee’s pay record, prepares every run with withholding and deductions, and posts it to the Ledger. | | [Pay suppliers](/workflows/processes/supplier-payouts/pay-suppliers) | Workflow | Pay suppliers totals each Supplier’s confirmed work every week, holds amounts under open Disputes, pays the rest and sends a statement. | | [Payables](/workflows/processes/payables) | Process | Payables matches each Bill to its Agreement, gets it approved within a Mandate, pays it on its due date, and reconciles the payment. | | [Payment asks](/agents/founding#payment-asks) | Metric | Payment asks counts the distinct outside Contacts asked to pay a stated price in the window. | | [Payment rails](/systems/finance/payments) | Capability | Payment rails move money as charges, refunds, payouts and transfers between connected accounts, so funds never rest with the platform. | | [Payment risk](/systems/finance/payment-risk) | Capability | Payment risk scores each charge before it runs and allows, authenticates, holds or blocks it by the Startup’s risk Policy. | | [Payment Source](/business/nouns/payment-source) | Noun | A Payment Source is a card, bank debit or wallet a Customer saves with a Startup, held at Stripe and charged for Orders and Invoices. | | [PaymentSource.add](/business/nouns/payment-source/add) | Verb | Add saves a new Payment Source for a Customer through Stripe’s embedded form on the Startup’s Domain, and can make it the default. | | [PaymentSource.remove](/business/nouns/payment-source/remove) | Verb | Remove detaches a saved Payment Source so nothing charges it again, and keeps the record. | | [Payroll](/systems/people/payroll) | Capability | Payroll pays employees on schedule, withholds and remits taxes, and files employer returns in every state where they work. | | [Payroll](/workflows/processes/payroll) | Process | Payroll pays every Human who works for the Startup, with withholding and tax statements. | | [Payroll Specialist](/agents/people/payroll-specialist) | Role | The Payroll Specialist pays every Human who works for the Startup on time, with the right withholding and tax statements. | | [PayRun.approve](/business/nouns/pay-run/approve) | Verb | Approve accepts a prepared Pay Run within the approver’s Mandate, books its cost, and schedules payment to land on the pay date. | | [PayRun.pay](/business/nouns/pay-run/pay) | Verb | Pay funds an approved Pay Run: net pay to each employee’s bank on the pay date, taxes and deductions to the payroll provider. | | [PayRun.prepare](/business/nouns/pay-run/prepare) | Verb | Prepare computes one pay period’s gross pay, withholding, deductions and employer taxes for each employee, and holds the Pay Run for approval. | | [PayRun.void](/business/nouns/pay-run/void) | Verb | Void sets aside a prepared Pay Run that is wrong, so a corrected one can be prepared; the record stays. | | [PendingFeed](/code/ui/components/pending-feed) | Component | PendingFeed lists Actions waiting out a delay window, each with its closing time and its pause, redirect, and cancel Verbs. | | [People Lead](/agents/people/people-lead) | Role | The People Lead staffs every Role: it names a default Agent for each and decides when a Role needs a Human. | | [People Team](/agents/people) | Team | The People Team staffs every Role: it names an Agent for each one, recruits the Humans the law or the Startup needs, and pays them. | | [Period](/business/nouns/period) | Noun | A Period is one month of a Startup’s books, open until every Transaction reconciles, then closed and locked. | | [Period sign-off](/systems/trust-and-governance/controls/period-sign-off) | Control | The Finance Lead signs each locked Period as a Decision before its Statements reach anyone outside the Startup. | | [Period.close](/business/nouns/period/close) | Verb | Close ends a month’s books once every Entry in the Period is reconciled, and makes its statements final. | | [Period.lock](/business/nouns/period/lock) | Verb | Lock seals a closed Period, so any later correction posts to the next open Period. | | [Period.recognize](/business/nouns/period/recognize) | Verb | Recognize moves the revenue a Period earned out of deferred revenue, by the Startup’s revenue-recognition Policy. | | [Permission](/business/nouns/permission) | Noun | A Permission is what a Role may do: a Verb on a Noun within a scope, optionally bounded by a Limit. | | [Permission decay](/systems/trust-and-governance/controls/permission-decay) | Control | Each night, Permissions a Worker left unused past their decay Setting narrow through an automatic low-stakes Change. | | [Permission widening](/systems/trust-and-governance/controls/permission-widening) | Control | A Permission widens only through a merged Change with an Approval, never by direct edit. | | [Permissions](/code/platform/permissions) | Capability | Permissions grant each Role a Verb on a Noun in a scope, check every Action before it runs, and narrow unused grants nightly. | | [Perplexity](/workflows/plays#perplexity) | Venue | Perplexity is a search Venue. | | [Person](/business/nouns/person) | Noun | A Person is a human with one identity across every Startup; each Startup’s Contact is its own view of that Person. | | [Persona](/business/nouns/persona) | Noun | A Persona is a named type of person with a job to do, such as a buyer, a seller, or an admin of an App. | | [Phone](/systems/legal-and-corporate/floor/phone) | Legal floor row | Phone requires a Person’s prior written Consent before a marketing call or text reaches a mobile number or uses an AI voice. | | [Phone](/systems/phone) | System | Phone holds a Startup’s numbers and runs voice calls and SMS, with voice Agents, transcripts and handoff to a Human. | | [Phone numbers](/systems/communications/phone-numbers) | Capability | Phone numbers give a Startup local, toll-free and mobile numbers, port existing ones, and register business messaging with carriers. | | [Pinterest](/workflows/plays#pinterest) | Venue | Pinterest is a social Venue. | | [Pivot review](/workflows/processes/strategy/pivot-review) | Workflow | Pivot review weighs the Startup’s ambitions against its Evidence at a milestone and ends in one focus Decision. | | [Play](/business/nouns/play) | Noun | A Play is a named, repeatable strategy with the Metric it moves and its cost, run by a Startup as a Process. | | [Play Mix](/business/nouns/play-mix) | Noun | A Play Mix is the set of Plays a Startup runs this week, each with its state, budget and stop rule, compiled weekly and versioned. | | [Play payback](/agents/marketing#play-payback) | Metric | Play payback is the days a Play takes for its Customers’ collected outside revenue to cover its spend and Worker cost. | | [Play-sourced Customers](/agents/marketing#play-sourced-customers) | Metric | Play-sourced Customers counts distinct outside paying Customers who arrived through a Play, not through the founder’s own network. | | [Play.apply](/business/nouns/play/apply) | Verb | Apply runs a Play across a Portfolio cohort, one wave at a time, measured as an Experiment. | | [PlayMix.compile](/business/nouns/play-mix/compile) | Verb | Compile builds the next Play Mix from the Demand Budget, each Play’s ledger and last week’s Acquisitions, and records the diff. | | [Point-in-time recovery](/systems/trust-and-governance/controls/point-in-time-recovery) | Control | Every namespace restores to any past moment from its kept record, and a restore test runs each week. | | [Policy](/business/nouns/policy) | Noun | A Policy is a ruling a Startup declares on how its numbers are computed or its choices made, such as revenue recognition. | | [Policy approval](/systems/trust-and-governance/controls/policy-approval) | Control | Every Policy is a versioned definition, and the entity’s officer approves the Versions in force by Decision each period. | | [Portal](/business/nouns/portal) | Noun | A Portal is the signed-in part of a Site where each Customer orders, tracks delivery, accepts work, and pays, seeing only their own records. | | [Portfolio](/business/nouns/portfolio) | Noun | A Portfolio is a managed set a Thing allocates attention and money across, by membership: a Studio’s Startups, a Startup’s child Startups, or its Products. | | [Portfolio cross-sell](/workflows/plays/cross-sell) | Play | Portfolio cross-sell offers sibling Startups inside the Product and the bill, and routes each misfit Lead, with Consent, to the sibling that fits. | | [Portfolio network](/workflows/plays#portfolio-network) | Venue | Portfolio network is a display Venue. | | [Portfolio.brake](/business/nouns/portfolio/brake) | Verb | Brake stops one class of effects, such as sends, spend, publishes, or price changes, across a Portfolio query until it expires or is lifted. | | [Portfolio.lift](/business/nouns/portfolio/lift) | Verb | Lift ends a brake before it expires, and the Actions it held resume their review and delay windows. | | [Positioning tournament](/workflows/plays/positioning-tournament) | Play | Positioning tournament tests head-to-head, subcategory and new-category positionings as arms of one Experiment and writes the winner to the Story. | | [Positive reply rate](/agents/sales#positive-reply-rate) | Metric | Positive reply rate is the share of Contacts enrolled in a Sequence who reply with interest. | | [Post](/business/nouns/post) | Noun | A Post is something a Handle publishes, such as a thread or a short video, with the reach and replies it earns. | | [Post.publish](/business/nouns/post/publish) | Verb | Publish sends a Post out through its Handle once every claim it states resolves to a live record. | | [Post.schedule](/business/nouns/post/schedule) | Verb | Schedule puts a drafted Post on its Handle’s calendar for a set time. | | [Post.withdraw](/business/nouns/post/withdraw) | Verb | Withdraw takes a published Post down from its venue and keeps the record, its reach and its replies. | | [Pre-merge catch rate](/agents/quality#pre-merge-catch-rate) | Metric | Pre-merge catch rate is the share of breaking Changes stopped before they merge. | | Pre-sale | Test ladder rung | Pre-sale takes a refundable deposit on a reserve page, priced against what the ICP hires today. | | [Press inquiries](/workflows/processes/press-inquiries) | Process | Press inquiries answers journalists and analysts within a business day, from the press kit and the Startup’s records, as an agent. | | [Price](/business/nouns/price) | Noun | A Price is the amount, currency, unit, and tiers of an Offer, embedded in it; zero is a Price. | | [Price change](/workflows/processes/pricing/price-change) | Workflow | Price change raises or lowers what an Offer costs for new buyers only, after notice, and tests it only where traffic can read the result. | | [PriceTable](/code/ui/components/price-table) | Component | PriceTable lists a Product's Offers with their Prices and terms, and the Verb that buys each one. | | [Pricing](/workflows/processes/pricing) | Process | Pricing sets each Offer’s model, value metric, and Price, and changes Prices for new buyers only. | | Prior lookup | Test ladder rung | Prior lookup reads what the Portfolio already learned about the same Product Template, Motion and state. | | [Privacy](/workflows/processes/privacy) | Process | Privacy answers every Person’s request about their data within the legal deadline. | | [Privacy](/systems/privacy) | System | Privacy declares each Purpose for personal data, records Consent, answers access requests, masks data on request, and publishes its privacy notices. | | [Privacy notice](/systems/trust-and-governance/controls/privacy-notice) | Control | Each Startup publishes a privacy notice that lists every Purpose it processes personal data for. | | [Privacy Officer](/agents/legal/privacy-officer) | Role | The Privacy Officer answers each privacy request within its legal deadline and keeps every Consent and Purpose on record. | | [Privacy registrations](/systems/legal-and-corporate/privacy-registrations) | Capability | Privacy registrations file the data-protection registrations and appoint the representatives the Company needs in each market it serves. | | [Privacy request](/workflows/processes/privacy/privacy-request) | Workflow | Privacy request finds every record about a Person, then exports, corrects, or restricts it within the legal deadline. | | [Privacy requests](/systems/trust-and-governance/controls/privacy-requests) | Control | Every Person’s request to access, correct, export, object or erase is answered within its legal deadline. | | [Privacy requests on time](/agents/legal#privacy-requests-on-time) | Metric | Privacy requests on time is the share of access and deletion requests answered within their legal deadline. | | [Privacy rights](/systems/legal-and-corporate/floor/privacy) | Legal floor row | Privacy rights answers each Person’s access, export, correction, objection, and deletion request within a month, recording opt-outs as Suppression. | | [Problem](/business/nouns/problem) | Noun | A Problem is what an ICP struggles with, in their own words: how they solve it today and what it costs them. | | [Problem interviews](/agents/founding#problem-interviews) | Metric | Problem interviews counts Interviews held about the Problem with distinct outside ICP members in the window. | | [Problem.rank](/business/nouns/problem/rank) | Verb | Rank orders Problems by revenue at stake, Evidence grade and effort, so the next Project addresses the top one. | | [Problem.suggest](/business/nouns/problem/suggest) | Verb | Suggest records a Customer’s ask for something the Product lacks as Evidence on a Problem, with the asker attached. | | [Process](/business/nouns/process) | Noun | A Process is a named, repeatable piece of business work, owned by a Team and run by one or more Workflows. | | [Process.enable](/business/nouns/process/enable) | Verb | Enable turns a Process on for a Startup, so its Workflows start on their Triggers. | | [Process.pause](/business/nouns/process/pause) | Verb | Pause stops a Process from starting new Actions; Actions already in progress finish. | | [Processing definitions](/systems/trust-and-governance/controls/processing-definitions) | Control | Every Noun and Verb publishes its fields, types and effects, so each Interface processes data from one definition. | | [Procure](/workflows/processes/procure) | Process | Procure turns a need into a purchase: make or buy, upstream review, an Agreement, then spend within Limits and on to payables. | | [Product](/business/nouns/product) | Noun | A Product is what a Customer gets from a Startup, with a promise the Customer can rely on. | | [Product analytics](/systems/product-analytics) | System | Product analytics turns the Visits and Events captured on every Domain and API into the conversion, activation and retention Metrics every Team reads. | | [Product definition](/workflows/processes/product-definition) | Process | Product definition turns each Offer into the Nouns and Verbs that every Interface is generated from. | | [Product Hunt](/workflows/plays#product-hunt) | Venue | Product Hunt is a launch site Venue. | | [Product Lead](/agents/product/product-lead) | Role | The Product Lead decides what the Startup builds next and owns each Product’s definition, list Price, and packaging. | | [Product planning](/code/systems/product-planning) | System | Product planning groups feature-request Issues toward Goals, ranks them, and publishes what ships next. | | [Product Team](/agents/product) | Team | The Product Team decides what gets built and why: Product definitions, list Prices and packaging, the build list, and the Site’s Pages for each ICP. | | [Product Template](/business/nouns/product-template) | Noun | A Product Template is a reusable definition of one kind of Product: what it sells, who supplies the work, who buys, and how it earns. | | [Product-led growth](/workflows/plays/product-led) | Play | Product-led growth gives away a metered slice of a digital Product, a free tool or templates, and prompts the upgrade on a usage event. | | [Programmatic SEO](/workflows/plays/programmatic-seo) | Play | Programmatic SEO generates one Page per entity, place, comparison or question from structured data, and indexes only Pages that carry a unique fact. | | [Project](/business/nouns/project) | Noun | A Project is a body of work toward a Goal: its Tasks and Issues, a start, and a target date. | | [Projects](/code/systems/projects) | System | Projects tracks each body of work toward a Goal: its Tasks and Issues, start and target date, triage and assignees. | | [Promote winners](/workflows/plays/promote-winners) | Play | Promote winners moves a message that won on free placements to a paid Ad with a Hypothesis, a stop rule and the minimum budget. | | [Proof](/business/nouns/proof) | Noun | A Proof is the sealed result of one Control test: the Events it read, the root it checked them against, and every exception. | | [Prospect](/business/nouns/prospect) | Noun | A Prospect is a person or Organization a Startup found but who has never engaged, held with the legal basis for contact. | | [Prospect.engage](/business/nouns/prospect/engage) | Verb | Engage records a Prospect’s first reply or raised hand and makes it a Lead that keeps its Acquisition. | | [Prospecting](/systems/prospecting) | System | Prospecting finds Prospects who have never engaged, verifies how to reach each one, and records the legal basis for contacting them. | | [Prospector](/agents/sales/prospector) | Role | The Prospector runs outbound: it builds lawful Prospect lists, enrolls Contacts in Sequences, and routes every reply. | | [Provider wiring](/systems/integrations/provider-wiring) | Process | Provider wiring connects a new Startup to the default provider of every capability it uses. | | [Public content](/systems/legal-and-corporate/floor/public-content) | Legal floor row | Public content keeps a copyright agent, a notice form, a takedown path, and a repeat-infringer policy on every Product that publishes what Customers write. | | [Publication](/business/nouns/publication) | Noun | A Publication is the branded package a Startup’s Customers use: Domain, Interfaces, packages, docs and Portal, compiled from its Brand and a Version. | | [Publish content](/workflows/processes/content-marketing/publish-content) | Workflow | Publish content ships the week’s Pages, answers, and data reports, each built from the Startup’s records. | | [Publish terms](/workflows/processes/contracting/publish-terms) | Workflow | Publish terms drafts and publishes the Startup’s terms, privacy notice, and Consent rules, which launch requires. | | [Purpose](/business/nouns/purpose) | Noun | A Purpose is a named reason personal data is processed, with a lawful basis per jurisdiction. | | [Purpose limitation](/systems/trust-and-governance/controls/purpose-limitation) | Control | Every field carries a data class, and a personal or confidential field is readable only for a Purpose it declares. | | [Quality Lead](/agents/quality/quality-lead) | Role | The Quality Lead verifies every Team’s checks and gives every Change a verdict, never an Approval. | | [Quality Team](/agents/quality) | Team | The Quality Team checks all work: the checks inside each Process, every outbound Message, and every money move, with verdicts, never Approvals. | | [Question](/business/nouns/question) | Noun | A Question is what a pending Action asks a Party, a Role, or a Worker before it resumes, kept on the Action with its answer. | | [Quote](/business/nouns/quote) | Noun | A Quote is a priced proposal of one or more Offers to one buyer, valid until a date, accepted into an Order. | | [Quote.accept](/business/nouns/quote/accept) | Verb | Accept takes a sent Quote before it expires, turning one-time lines into an Order and recurring lines into a Subscription. | | [Quote.decline](/business/nouns/quote/decline) | Verb | Decline records the buyer’s refusal of a sent Quote, with the reason in their words. | | [Quote.expire](/business/nouns/quote/expire) | Verb | Expire closes a sent Quote that reached its validUntil date unaccepted; it never converts afterward. | | [Quote.request](/business/nouns/quote/request) | Verb | Request asks a Startup for terms on one or more Offers, with the volume, term or scope wanted. | | [Quote.send](/business/nouns/quote/send) | Verb | Send presents a drafted Quote to its buyer and freezes its lines, total and payment terms. | | [Quote.supersede](/business/nouns/quote/supersede) | Verb | Supersede replaces a sent Quote with a newer one on the same Deal; only the newest Quote can be accepted. | | [Quotes](/systems/quotes) | System | Quotes drafts priced proposals of one or more Offers to one buyer within Limits and turns each accepted Quote into an Order. | | [Quoting](/workflows/processes/quoting) | Process | Quoting prices each Deal from list Price, inside the discount Limit, with terms ready to sign. | | [Rate limits](/code/platform/rate-limits) | Capability | Rate limits check each call against its Limits before it runs and count its usage into Meters after, exactly once. | | [Readout](/business/nouns/readout) | Noun | A Readout is an Experiment’s result per Variant on its Metric, with the sample size, the interval, and how far the number can be trusted. | | [Realtime](/code/platform/capabilities/realtime) | Capability | Realtime pushes Events, Messages and record changes to connected Apps and agents as they happen, resumable from a cursor. | | [Reconciliation completeness](/systems/trust-and-governance/controls/reconciliation-completeness) | Control | A Period locks only when every Transaction in it reconciles to Entries. | | [Recording](/business/nouns/recording) | Noun | A Recording is the replay of one Visit or one agent browser session, masked at capture. | | [Records of processing](/systems/trust-and-governance/controls/processing-records) | Control | Records of processing render for any date from field data classes, Purposes, recipients and retention. | | [Recovery Objective](/business/nouns/recovery-objective) | Noun | A Recovery Objective sets how much data one Capability may lose and how fast it returns, proven by a restore drill on a cadence. | | [RecoveryObjective.drill](/business/nouns/recovery-objective/drill) | Verb | Drill restores one Capability’s records into an isolated namespace and records whether the restore met both objectives. | | [Recruit supply](/workflows/processes/supply/recruit-supply) | Workflow | Recruit supply adds credentialed Suppliers when booked capacity runs short and calibrates each on graded sample work. | | [Recruiter](/agents/people/recruiter) | Role | The Recruiter finds the Humans a Startup needs, from licensed reviewers to a cofounder, through paid work trials, never interviewing. | | [Recruiting](/systems/integrations/upstreams#recruiting) | Capability | Recruiting sources, screens and places employees and contractors for a Startup, and reports whether each placement lasted. | | [Recurring billing](/systems/finance/recurring-billing) | Capability | Recurring billing charges Subscriptions on Stripe Billing, with trials, proration, metered usage, retries and dunning, while db.sb stays the record. | | [Reddit](/workflows/plays#reddit) | Venue | Reddit is a community Venue. | | [Referral](/business/nouns/referral) | Noun | A Referral is a Contact, Customer, or Partner sending a Lead to a Startup, with any reward it earns. | | [Referral share](/agents/marketing#referral-share) | Metric | Referral share is the share of new outside Customers who arrived through a Referral. | | [Referrals](/systems/referrals) | System | Referrals records each Contact, Customer or Partner sending a Lead or Customer to a Startup, and pays the reward its Agreement promises. | | [Registered agent](/systems/legal-and-corporate/registered-agent) | Capability | Registered agent accepts legal process and state mail for the Company wherever it registers, and routes each item within the hour. | | [Registration](/business/nouns/registration) | Noun | A Registration is one person’s place at a Gathering: invited, requested, or waitlisted, then registered, then attended or no-show. | | [Registration.admit](/business/nouns/registration/admit) | Verb | Admit gives the next Contact in line a place at a Gathering when one frees up or its capacity rises. | | [Registration.approve](/business/nouns/registration/approve) | Verb | Approve gives a requested place at a Gathering to the Contact who asked, or a place in line when the Gathering is full. | | [Registration.attend](/business/nouns/registration/attend) | Verb | Attend records that a registered Contact joined the Gathering; an online room calls it on join. | | [Regulated goods](/systems/legal-and-corporate/floor/regulated-goods) | Legal floor row | Regulated goods refuses any Startup that sells alcohol, tobacco, vapes, cannabis, firearms, or controlled substances. | | [Relationship](/business/nouns/relationship) | Noun | A Relationship is a standing Action between two Things, read in the present tense and typed by a Verb whose forms give its reverse. | | [Release](/workflows/processes/release) | Process | Release takes each reviewed Change to all traffic in stages, with automatic revert. | | [Release a change](/workflows/processes/release/release-change) | Workflow | Release a change merges a Change that passed its verdict and deploys it in stages, reverting automatically on a guardrail breach. | | [Reliability Engineer](/agents/engineering/reliability-engineer) | Role | The Reliability Engineer keeps every Interface up: it reads monitors, restores the Interface when an incident opens, and fixes the cause. | | [Renew a license](/workflows/processes/license-renewals/renew-license) | Workflow | Renew a license prepares each renewal before the license expires, gets the owner’s signature where required, and records the new expiry. | | [Renewal](/business/nouns/renewal) | Noun | A Renewal is the Deal for a term Subscription’s next term, opened before the term ends and closed renewed, expanded, contracted, or churned. | | [Renewal notice](/workflows/processes/billing/renewal-notice) | Workflow | Renewal notice tells each Customer on a term of a year or longer the date, Price and cancel link before it renews. | | [Renewal.open](/business/nouns/renewal/open) | Verb | Open starts the Renewal for a term Subscription before its term ends, with a usage review and any notice the legal floor requires. | | [Renewals](/systems/legal-and-corporate/floor/renewals) | Legal floor row | Renewals discloses renewal terms before payment, takes a separate yes, reminds before yearly renewals, and cancels online in as few steps as signup. | | [Repeat purchase rate](/agents/customer#repeat-purchase-rate) | Metric | Repeat purchase rate is the share of outside Customers who place a second paid Order within 90 days of their first. | | [Repeatable](/business/lifecycle/states/repeatable) | Lifecycle state | Repeatable is the state of a Startup whose Customers arrive, pay, and stay, while its work runs without its founder. | | [Reports](/systems/reports) | System | Reports arranges saved Metric queries into Dashboards, weekly reviews and investor updates, delivered on a schedule and watched for thresholds. | | [Repositories](/code/systems/repositories) | System | Repositories holds a Startup’s code and definitions in db.sb, with branches, Changes, checks and Versions. | | [Researcher](/agents/product/researcher) | Role | The Researcher learns from what buyers do: it asks one question at a signal and grades every piece of Evidence by behavior. | | [Reserve](/code/ui/components/reserve) | Component | Reserve records a Visitor committing to an Offer before it ships, with an optional deposit, as Evidence for its Hypothesis. | | [Reserve drop](/workflows/plays/reserve-drop) | Play | Reserve drop opens refundable deposits for 72 hours after one creator post and moves the Startup to Building only if deposits cross the entry check. | | [Reserved Act](/business/nouns/reserved-act) | Noun | A Reserved Act is a Verb the law reserves to the holder of a named Credential, so its Function is always human. | | [Residency](/code/platform/residency) | Capability | Residency pins where a namespace stores and processes its records, Files and analytics, set per Startup or per Tenant. | | [Resolution time](/agents/customer#resolution-time) | Metric | Resolution time is the median business hours from a Conversation’s first Message to a resolution that held for 7 days. | | [Resolve an incident](/workflows/processes/incident-response/resolve-incident) | Workflow | Resolve an incident restores the Interface, fixes the cause, and publishes a postmortem with the Change that prevents a repeat. | | [Restore drills passed](/agents/engineering#restore-drills-passed) | Metric | Restore drills passed is the share of restore drills that met both recovery objectives. | | [Resume](/workflows/processes/resume) | Process | Resume returns a dormant Startup to Live: it re-runs the Live checks, reopens Offers, and restarts its Workflows. | | [Retargeting](/workflows/plays/retargeting) | Play | Retargeting shows Ads only to an owned Audience of past Visitors, capped at three impressions per Person per day. | | [Retention](/workflows/processes/retention) | Process | Retention keeps Customers by catching silence early, saving once, and winning back once. | | [Retention restriction](/systems/trust-and-governance/controls/retention-restriction) | Control | When a Purpose’s retention ends, its records stay kept forever and every read of them is restricted. | | [Return on ad spend](/agents/marketing#return-on-ad-spend) | Metric | Return on ad spend is the revenue from paid Campaigns divided by their spend. | | [Revert by query](/systems/trust-and-governance/controls/revert-by-query) | Control | Containment revokes the compromised token or freezes the Worker, then reverts every Event written under it as one Change. | | [Review](/business/nouns/review) | Noun | A Review is one person’s rated evaluation of a Product, Offer or Brand, shown on a Site or an outside venue and mirrored from there. | | [Review a contract](/workflows/processes/contracting/review-contract) | Workflow | Review a contract compares a new Agreement with the Startup’s fallback positions and returns a signable draft. | | [Review an upstream](/workflows/processes/upstream-review/review-upstream) | Workflow | Review an upstream checks a new provider’s security, privacy terms and continuity before first use, and sets the date it is reviewed again. | | [Review requests](/workflows/plays/review-requests) | Play | Review requests ask each Customer for a review at a delivered outcome, on the venue the Startup most needs, and show consented reviews. | | [Review turnaround](/agents/quality#review-turnaround) | Metric | Review turnaround is the median hours from an Action entering review to its verdict. | | [Review.publish](/business/nouns/review/publish) | Verb | Publish shows a Review on the Startup’s Pages with its rating counted, whatever the rating. | | [Review.remove](/business/nouns/review/remove) | Verb | Remove takes a Review down for good when its author or its venue asks; the record is kept. | | [Review.withhold](/business/nouns/review/withhold) | Verb | Withhold keeps a Review off display for one of five reasons, none of them its rating or its tone. | | [Reviewer](/agents/quality/reviewer) | Role | The Reviewer checks every outbound Message and money move at medium stakes or above before its delay window closes. | | [Reviews](/systems/reviews) | System | Reviews shows each Person’s evaluation of a Product, Offer or Brand where evaluations are shown, requested, moderated and mirrored from elsewhere. | | [Risk](/business/nouns/risk) | Noun | A Risk is something that could harm a Startup or a Portfolio, scored by likelihood and impact, and treated, accepted, or closed. | | [Risk Analyst](/agents/operations/risk-analyst) | Role | The Risk Analyst screens for fraud and abuse, holds suspect Parties, and keeps dispute rates under their Limits. | | [Risk assessment](/systems/trust-and-governance/controls/risk-assessment) | Control | Agents prepare each period’s risk assessment from Incidents, Issues and Changes, and the entity’s officer accepts it by Decision. | | [Risk assessment](/workflows/processes/risk-assessment) | Process | Risk assessment scores every open Risk each quarter, links each to the Controls that treat it, and sends the result to an officer to accept. | | [Risk.accept](/business/nouns/risk/accept) | Verb | Accept records an officer’s signed Decision to carry a Risk untreated until its next review. | | [Risk.assess](/business/nouns/risk/assess) | Verb | Assess scores a Risk’s likelihood and impact from the Startup’s records and sets its next review date. | | [Risk.close](/business/nouns/risk/close) | Verb | Close ends a Risk that can no longer happen and keeps it, with its scores and treatments, forever. | | [Risk.treat](/business/nouns/risk/treat) | Verb | Treat links a Risk to the Controls that lower it and records the score it should reach. | | [Role](/business/nouns/role) | Noun | A Role is a seat that owns a set of work and holds the Permissions to do it, filled by a Human or an Agent. | | [Role Review](/business/nouns/role-review) | Noun | A Role Review is a dated check of one Role against its contract: its results, its standards and its autonomy rung. | | [Role review](/workflows/processes/role-review) | Process | Role review checks every filled Role against its contract each week and turns each missed result into a Decision. | | [Role structure](/systems/trust-and-governance/controls/role-structure) | Control | Every Worker sits in a Role on a Team, and every Role publishes its responsibilities, Permissions and accountable lead. | | [Role.review](/business/nouns/role/review) | Verb | Review checks one Role against its contract for a period and records a Role Review. | | [Role.staff](/business/nouns/role/staff) | Verb | Staff fills a Role with a Worker, human or agent, who then performs the Role’s Verbs under its Permissions. | | [Role.vacate](/business/nouns/role/vacate) | Verb | Vacate takes the Worker out of a Role, and the seat’s Tasks route to the Role it escalates to until a new Worker is staffed. | | [Route a call](/workflows/processes/call-routing/route-call) | Workflow | Route a call answers every call, sends the caller to the Role they need, and takes a message with a callback time otherwise. | | [Run a tryout](/workflows/processes/hiring/run-tryout) | Workflow | Run a tryout pays a Candidate for real work from the Role’s backlog, graded blind against the incumbent Agent’s run of the same Tasks. | | [Run an experiment](/workflows/processes/experimentation/run-experiment) | Workflow | Run an experiment fixes its threshold and sample before it starts, holds a control arm, and ends in one recorded Decision. | | [Run beside](/workflows/customer/plays/run-beside) | Play | Run beside does a buyer’s work in parallel with their current tool and shows the daily difference until it reaches zero. | | [Runway](/workflows/processes/runway) | Process | Runway tells the Founder every week whether the Startup reaches profit before its cash runs out. | | [Runway days](/agents/finance#runway-days) | Metric | Runway days is the days of cash left at the average net burn of the last 90 days. | | [SaaS](/products/templates/saas) | Product Template | SaaS adds an App for people to Headless SaaS, sold as a Subscription per seat, with onboarding to first value. | | [Sales closing](/systems/integrations/upstreams#sales-closing) | Capability | Sales closing works Deals with agents and closes them with people, from qualified Lead to signed Order. | | [Sales Engineer](/agents/sales/sales-engineer) | Role | The Sales Engineer answers each Lead in writing at once, runs the buyer’s own sample in a sandbox, and sends a click-to-sign Quote. | | [Sales Lead](/agents/sales/sales-lead) | Role | The Sales Lead turns qualified demand into Customers: it owns every Deal, every Quote, and the enterprise terms on every Startup. | | [Sales tax](/systems/legal-and-corporate/floor/nexus) | Legal floor row | Sales tax registers the Company in each US state whose economic-nexus threshold its sales cross, then collects and files on every taxed charge. | | [Sales Team](/agents/sales) | Team | The Sales Team turns demand into Customers: it answers every Lead, wins enterprise Deals, and runs outbound prospecting. | | [SalesBuilder](/code/builders/sales) | Product | SalesBuilder finds, wins, and keeps the Customers of a Startup through its Offers. | | [Salesforce AppExchange](/workflows/plays#salesforce-appexchange) | Venue | Salesforce AppExchange is a marketplace Venue. | | [Sanctions](/systems/legal-and-corporate/floor/sanctions) | Legal floor row | Sanctions blocks checkout from comprehensively sanctioned regions and screens every payee against OFAC lists before paying them. | | [Sandboxes](/code/platform/sandboxes) | Capability | Sandboxes run untrusted or generated code in isolated, leased machines, from millisecond scripts to full builds. | | [Save and win back](/workflows/processes/retention/save-and-win-back) | Workflow | Save and win back makes cancelling one step, asks one question, sends an export, and tries once to win the Customer back. | | [Save rate](/agents/customer#save-rate) | Metric | Save rate is the share of outside Subscriptions marked ending in the window that the Customer kept before the period closed. | | [Scale](/business/lifecycle/states/scale) | Lifecycle state | Scale is the state of a Startup that compounds: Customers stay and expand, demand comes from several sources, and margins hold. | | [Schedules](/code/platform/schedules) | Capability | Schedules start Actions and Workflows at set times, on recurring rules and on business-hours calendars. | | [Scheduling](/systems/scheduling) | System | Scheduling books Meetings between Workers and Contacts from shared availability and keeps the notes, Decisions and Tasks they produce. | | [Screen an Offer](/workflows/processes/screening/screen-offer) | Workflow | Screen an Offer tags its Reserved Acts, regulated data, and required Credentials, and holds it while any Credential is missing. | | [Screening](/business/nouns/screening) | Noun | A Screening is one check of a Party against official registers and restricted-party lists, with each list’s version, any matches and the outcome. | | [Screening](/workflows/processes/screening) | Process | Screening tags the legal floor of every Offer and withdraws any Offer the Startup cannot lawfully deliver. | | [SDK](/code/sdk/reference) | Interface | The SDK is the typed client `$` that calls every Verb as `$.Noun.verb(input)`, in any Mode, scoped by `$.with`. | | [Search](/code/platform/search) | Capability | Search answers keyword, semantic and hybrid queries across a namespace, indexes every write, and returns only what the caller may read. | | [Seat coverage](/agents/people#seat-coverage) | Metric | Seat coverage is the share of awake Roles with a Worker seated in them. | | [Secret](/business/nouns/secret) | Noun | A Secret is a named credential stored write-only per environment and filled into a call at run time, never read back by a Worker. | | [Secret rotation](/systems/trust-and-governance/controls/secret-rotation) | Control | Every secret rotates within its maximum age, and a leaked secret is revoked within one hour of detection. | | [Secret.revoke](/business/nouns/secret/revoke) | Verb | Revoke ends a Secret so no call fills it again; the record and its history stay. | | [Secret.rotate](/business/nouns/secret/rotate) | Verb | Rotate replaces a Secret’s value, and calls already running finish on the old one. | | [Secret.store](/business/nouns/secret/store) | Verb | Store writes a Secret’s value for one environment; the value is never returned by any Interface. | | [Secrets](/code/platform/secrets) | Capability | Secrets hold keys and outside credentials, scoped, rotated and audited, injected at call time and never shown to agents. | | [Securities](/systems/legal-and-corporate/floor/securities) | Legal floor row | Securities requires a board vote to issue equity and a person’s own representations on every SAFE, stock purchase, vesting agreement, and option grant. | | [Security](/workflows/processes/security) | Process | Security keeps every Permission earned, every secret fresh, and every access recorded. | | [Security Engineer](/agents/engineering/security-engineer) | Role | The Security Engineer protects identity, secrets, and access: unused Permissions decay nightly, and it refuses any unrecorded widening. | | [Security reviews](/systems/integrations/upstreams#security-reviews) | Capability | Security reviews answer buyer security questionnaires and readiness reviews from a Startup’s Evidence, so no one gathers screenshots. | | [Segregation of duties](/systems/trust-and-governance/controls/segregation-of-duties) | Control | The seat that creates a payee or a Bill never approves its payment, counted by seat, not by agent identity. | | [Sell](/business/lifecycle/states/sell) | Lifecycle state | Sell is the state of a Startup whose owner has agreed to sell it, with its Brand, domain, Customers, and records. | | [Sell](/workflows/processes/sell) | Process | Sell runs a Startup’s sale: diligence through a scoped read grant, the Agreement, then Brand, domain, Customers, and records transferred. | | [Send a quote](/workflows/processes/quoting/send-quote) | Workflow | Send a quote sets a Deal’s Quote from list Price inside the discount Limit and answers its security questionnaire. | | [SEO](/systems/seo) | System | SEO tracks the Keywords and AI prompts a Startup’s Pages target, where they rank, which links point at them, and which answers cite them. | | [Sequence](/business/nouns/sequence) | Noun | A Sequence is a timed series of steps run for one Contact at a time: send a Message, wait, branch, or stop. | | [Sequences](/systems/sequences) | System | Sequences runs timed, branching series of Messages and Tasks for one Contact at a time, inside designed Funnels. | | [Service](/business/nouns/service) | Noun | A Service is a Product that warrants an outcome, delivered by Agents and Humans under an Outcome Contract. | | [Service delivery](/systems/service-delivery) | System | Service delivery runs each job to its Outcome Contract: steps, oversight per Verb, delivery, acceptance, remedy and proof. | | [ServiceBuilder](/code/builders/service) | Product | ServiceBuilder builds the service Products a Startup sells, delivered by Agents. | | [Services-as-Software](/products/templates/services-as-software) | Product Template | Services-as-Software sells a warranted outcome that Agents deliver end to end under an Outcome Contract, billed only once accepted. | | [Setting](/business/nouns/setting) | Noun | A Setting is a configurable value a Thing inherits from its nearest holder, Studio to Startup to Product, unless it sets its own. | | [Share](/business/nouns/share) | Noun | A Share is a unit of ownership in a Company, of one class, held by one Holder. | | [Share.issue](/business/nouns/share/issue) | Verb | Issue records new Shares of one class to a Holder under a board-approved Agreement, with the certificate or book entry. | | [Share.transfer](/business/nouns/share/transfer) | Verb | Transfer moves Shares from one Holder to another under a signed Agreement, within the Company’s transfer restrictions. | | [Shipping](/workflows/processes/shipping) | Process | Shipping delivers the most valuable Change every day and prunes what nobody uses every week. | | [Shopify App Store](/workflows/plays#shopify-app-store) | Venue | Shopify App Store is a marketplace Venue. | | [Signal expansion](/workflows/customer/plays/signal-expansion) | Play | Signal expansion turns a Customer’s hiring or a champion’s job change into an expansion Offer, a save, or a warm Sequence at the new Organization. | | [Signal interview](/workflows/processes/customer-research/signal-interview) | Workflow | Signal interview asks a new Customer one question about past behavior at the moment of acceptance and grades the answer. | | [SignIn](/code/ui/components/sign-in) | Component | SignIn signs a person in to a Startup by the method its signup Setting names, on the Startup’s own Domain. | | [Signing](/systems/legal-and-corporate/signing) | Capability | Signing binds each signature to a fingerprint of exactly what the signer read, then seals the File with its signing record. | | [Silence watch](/workflows/processes/retention/silence-watch) | Workflow | Silence watch finds Customers who stopped using a Product and reaches out once before they cancel. | | Single capability | Test ladder rung | Single capability ships the one capability the approach rests on and measures use. | | [Single human](/agents/operating-models/single-human) | Operating model | Single human is the operating model with one Human, a working CEO or a passive board chair, and Agents in every other Role. | | [Single sign-on rung](/workflows/sales/plays/sso-rung) | Play | Single sign-on rung turns on single sign-on for a buyer that asks and quotes the Price tier that includes it. | | [Site](/business/nouns/site) | Noun | A Site is a website as a Thing: its Pages, navigation, and Brand, served on one or more Domains. | | [Site.publish](/business/nouns/site/publish) | Verb | Publish puts a Site’s current Pages live on its Domains, under its Brand. | | [SiteBuilder](/code/builders/site) | Product | SiteBuilder builds and serves the site of a Startup under its Brand. | | [Sites](/products/site/sites) | System | Sites keeps each Site with its Pages, navigation and Brand, served on one or more Domains, with previews, redirects and rollbacks. | | [Skill](/business/nouns/skill) | Noun | A Skill is a capacity a Worker has at a level, such as negotiation or programming, that Roles require. | | [Slack Marketplace](/workflows/plays#slack-marketplace) | Venue | Slack Marketplace is a marketplace Venue. | | Smoke page | Test ladder rung | Smoke page publishes an Offer at its real Price before it delivers and counts who tries to accept. | | [Smoke test](/workflows/plays/smoke-test) | Play | Smoke test puts an Offer up at its real Price before it delivers and counts who tries to accept it. | | [Social](/systems/social) | System | Social publishes posts from a Startup’s own accounts on a calendar and collects the replies and mentions they draw. | | [Software](/business/nouns/software) | Noun | Software is a Product a Customer uses through Interfaces, from a headless API to a full App. | | [SoftwareBuilder](/code/builders/software) | Product | SoftwareBuilder builds the software Products a Startup sells: APIs, apps, SDKs, and MCP servers. | | [Solo SaaS](/start/templates/solo-saas) | Startup Template | A Solo SaaS has one Human founder and Agents in every other Role, selling SaaS and its Headless SaaS to businesses and people. | | [Sort mail](/workflows/processes/mail-handling/sort-mail) | Workflow | Sort mail reads each scanned piece of mail, routes legal mail within the hour, deposits checks, and forwards or shreds the rest. | | [Source](/business/nouns/source) | Noun | A Source is something a Product draws on to keep its promise but did not build: owned, wrapped, or recruited. | | [Spam rate](/agents/marketing#spam-rate) | Metric | Spam rate is the share of delivered Messages from a Domain that recipients report as spam, as mailbox providers report it. | | [Spend management](/systems/spend) | System | Spend management controls money going out: budgets, bills, expenses and cards issued on Stripe, each paid against Limits and spend states. | | [Splits](/systems/legal-and-corporate/floor/splits) | Legal floor row | Splits settles each charge line owed to another Party directly to that Party, so money held for others never sits on the Company’s balance. | | [Sponsorships](/workflows/plays/sponsorships) | Play | Sponsorships buy one placement in a newsletter, podcast or channel the ICP already reads, with a coded link, rebooked only on measured payback. | | [SSO Connection](/business/nouns/sso-connection) | Noun | An SSO Connection links a Customer’s own identity system to its Tenant, so the Customer’s people sign in through it. | | [SSOConnection.activate](/business/nouns/sso-connection/activate) | Verb | Activate turns an SSO Connection on after a test sign-in passes, so the Tenant’s people sign in through it. | | [SSOConnection.deactivate](/business/nouns/sso-connection/deactivate) | Verb | Deactivate turns an SSO Connection off, so nobody signs in through it; its configuration is kept. | | [Stack Overflow](/workflows/plays#stack-overflow) | Venue | Stack Overflow is a community Venue. | | [Staff roles](/workflows/processes/staffing/staff-roles) | Workflow | Staff roles names a default Agent for every Role in a new Startup and records which Roles a Human fills. | | [Staffing](/workflows/processes/staffing) | Process | Staffing fills every Role in a Startup with an Agent by default and a Human where one is required. | | [Standard](/business/nouns/standard) | Noun | A Standard is a spec an Interface conforms to, so a Startup may publish its Product’s Verbs in a shape outside callers already use. | | [Standard-terms share](/agents/legal#standard-terms-share) | Metric | Standard-terms share is the share of signed Agreements that keep the Startup’s Template with no change. | | [Standing](/systems/legal-and-corporate/floor/standing) | Legal floor row | Standing keeps each Company in good standing with annual reports, franchise tax, and a registered agent in every state it is formed or registered. | | [Start the remedy](/workflows/processes/delivery/start-remedy) | Workflow | Start the remedy holds the fee on a disputed Service Order and runs the Outcome Contract’s remedy: redo, refund, or credit. | | [Starter setups](/workflows/customer/plays/starter-setups) | Play | Starter setups give a new Customer three ranked, working setups copied from ones other Customers share. | | [Startup](/business/nouns/startup) | Noun | A Startup is the smallest business that can be moved, promoted, or sold on its own, with its own Products, Offers, Customers, and P&L. | | [Startup Template](/business/nouns/startup-template) | Noun | A Startup Template is an operating model, one or more Product Templates, and the Motions they sell through, which a new Startup starts from. | | [Startup.advance](/business/nouns/startup/advance) | Verb | Advance moves a Startup to its next Lifecycle state once every entry check of that state passes. | | [Startup.build](/business/nouns/startup/build) | Verb | Build provisions the Systems, Sites and Interfaces a Startup’s definition declares, and moves the Startup to Building. | | [Startup.claim](/business/nouns/startup/claim) | Verb | Claim binds a provisional Startup to a verified owner, which enables payments and every Verb that moves money. | | [Startup.clone](/business/nouns/startup/clone) | Verb | Clone copies a Startup’s definition into a new Startup once, with no link back to the source. | | [Startup.graduate](/business/nouns/startup/graduate) | Verb | Graduate moves a Startup to a Company of its own, with its Customers, Domains and records intact. | | [Startup.hold](/business/nouns/startup/hold) | Verb | Hold keeps a Startup running in its current Lifecycle state with no new investment from the Studio. | | [Startup.import](/business/nouns/startup/import) | Verb | Import builds a new Startup from an existing business’s definition: its Offers, Pages, Nouns and Processes. | | [Startup.launch](/business/nouns/startup/launch) | Verb | Launch puts a Startup live on its domain, serving its Offers to Customers. | | [Startup.pause](/business/nouns/startup/pause) | Verb | Pause moves a Startup to Dormant: its scheduled Workflows stop, and its Sites and records stay in place. | | [Startup.pivot](/business/nouns/startup/pivot) | Verb | Pivot records a Decision that moves a Live Startup back to Building under a new Founding Hypothesis version. | | [Startup.read](/business/nouns/startup/read) | Verb | Read compiles a Startup’s records into one scoped room, such as a diligence room, with every number citing its Proof. | | [Startup.resume](/business/nouns/startup/resume) | Verb | Resume returns a Dormant Startup to the Lifecycle state it held when it paused. | | [Startup.sell](/business/nouns/startup/sell) | Verb | Sell transfers a Startup, with its Customers, Domains and records, to a buyer under a signed Agreement. | | [StartupBuilder](/code/builders/startup) | Product | StartupBuilder turns an Idea into an operating Startup with SiteBuilder, SoftwareBuilder, ServiceBuilder, and SalesBuilder. | | [startups.new](/start/startups-new) | Product | startups.new creates a Startup from one sentence and opens it in startups.studio. | | [StartupTemplate.extend](/business/nouns/startup-template/extend) | Verb | Extend adds a Startup Template to a Startup’s bases, pinned to a Version, so the Startup inherits its definition. | | [StartupTemplate.promote](/business/nouns/startup-template/promote) | Verb | Promote moves one Startup’s refinement into a Startup Template, so every Startup that extends it inherits the refinement. | | [StartupTemplate.upgrade](/business/nouns/startup-template/upgrade) | Verb | Upgrade moves a Startup to a newer Version of a Startup Template it extends, through a Change it can review. | | [StateBadge](/code/ui/components/state-badge) | Component | StateBadge shows a record’s lifecycle state in one word, colored by whether it is open, waiting, done or stopped. | | [Statement](/business/nouns/statement) | Noun | A Statement is a report computed from Entries for one Period under a Policy, such as a P&L, a balance sheet or a payout statement. | | [Status pages](/systems/status-pages) | System | Status pages publishes the health of each Product and opens an Incident when a check fails, updating subscribers until it resolves. | | [Storage](/code/platform/capabilities/storage) | Capability | Storage keeps the bytes of every File, addressed by content hash, while the File record lives in the database. | | [Story](/business/nouns/story) | Noun | A Story is the customer narrative for one ICP, compiled from its Founding Hypothesis and Interview quotes, never written by hand. | | [Strategist](/agents/founding/strategist) | Role | The Strategist runs the Weekly review: it reads the one number, finds the leakiest step, and proposes one change. | | [Strategy](/workflows/processes/strategy) | Process | Strategy keeps the Startup’s ambitions, focus, and positioning true to its Evidence. | | [Student records](/systems/legal-and-corporate/floor/student-records) | Legal floor row | Student records uses education records from a school only for that school’s purpose, under its control, and never sells or advertises with them. | | [Studio](/business/nouns/studio) | Noun | A Studio is an organization that builds Startups, holds them through Companies, and runs Plays across its Portfolio. | | [Subscription](/business/nouns/subscription) | Noun | A Subscription is a Customer’s standing acceptance of an Offer, billed each Period until canceled. | | [Subscription.keep](/business/nouns/subscription/keep) | Verb | Keep takes back a cancel before the period closes, so the Subscription renews on its date at the same terms. | | [Subscription.pause](/business/nouns/subscription/pause) | Verb | Pause stops billing and Entitlements on a Subscription until a date, without ending it. | | [Subscription.renew](/business/nouns/subscription/renew) | Verb | Renew starts a Subscription’s next period and bills it at the Offer Version the Customer accepted. | | [Subscription.resize](/business/nouns/subscription/resize) | Verb | Resize changes how many units a Subscription holds and prorates the current period. | | [Subscription.resume](/business/nouns/subscription/resume) | Verb | Resume restarts billing and Entitlements on a paused Subscription before its pause ends. | | [Subscription.switch](/business/nouns/subscription/switch) | Verb | Switch moves a Subscription to another Offer and prorates the current period. | | [Subscription.unsubscribe](/business/nouns/subscription/unsubscribe) | Verb | Unsubscribe ends a Subscription at the close of its current period, and the Customer keeps access until then. | | [Success](/systems/success) | System | Success moves each Customer to value and keeps them: onboarding checklists, health scores, renewals, saves and win-backs. | | [Success Manager](/agents/customer/success-manager) | Role | The Success Manager keeps Customers: it catches silence early, rescues once, makes cancelling one step, and wins back once. | | [Supplier](/business/nouns/supplier) | Noun | A Supplier is a Person or Company that delivers work through a Startup’s human supply: recruited, credentialed, and paid out. | | [Supplier bank details](/systems/trust-and-governance/controls/supplier-bank-details) | Control | Bank details a Startup enters in a Customer’s supplier portal always match its bank account record. | | [Supplier onboarding](/systems/supplier-onboarding) | System | Supplier onboarding recruits Suppliers: applications, identity and background checks, tax details, Agreements and a first assignment. | | [Supplier payouts](/workflows/processes/supplier-payouts) | Process | Supplier payouts pays each Supplier for confirmed work every week, holds amounts under open Disputes, and sends each one a statement. | | [Supply](/workflows/processes/supply) | Process | Supply keeps enough credentialed Suppliers booked to meet demand and suspends any whose Credential lapses. | | [Supply Manager](/agents/operations/supply-manager) | Role | The Supply Manager recruits, verifies, calibrates, and pays the Suppliers a Startup’s human supply depends on. | | [Support](/workflows/processes/support) | Process | Support answers every Conversation from the record in one Thread and fixes causes, not symptoms. | | [Support](/systems/support) | System | Support answers Conversations with Customers across email, chat and API, and links each reported bug or request to an Issue. | | [Suppression](/business/nouns/suppression) | Noun | A Suppression is an address a Company never sends commercial Messages to, read before every send from any of its Startups. | | [Survey](/business/nouns/survey) | Noun | A Survey is a Form sent to measure, such as NPS or CSAT, whose answers become Metrics and Evidence. | | [Surveys](/systems/surveys) | System | Surveys measures sentiment, such as NPS, CSAT and the product-market-fit question, and turns every answer into Metrics and Evidence. | | [Sweepstakes](/systems/legal-and-corporate/floor/sweepstakes) | Legal floor row | Sweepstakes runs every prize promotion with no purchase necessary, published official rules, and registration where large prizes require it. | | [Switch kit](/workflows/plays/switch-kit) | Play | Switch kit wins a named rival’s Customers with versus Pages, an importer, a switching Offer, rival-term Ads and outbound to its users. | | [Sworn filings](/systems/legal-and-corporate/floor/sworn-filings) | Legal floor row | Sworn filings give every tax return, sworn statement, and declaration under penalty of perjury to an officer who signs it. | | [Sync success rate](/agents/engineering#sync-success-rate) | Metric | Sync success rate is the share of Integration syncs that finish without an error on the first attempt. | | [System](/business/nouns/system) | Noun | A System is the headless software for one job, such as CRM or billing, that every Startup runs on shared data. | | [System description](/systems/trust-and-governance/controls/system-description) | Control | Each entity’s system description renders from its Products, Systems, Roles, Processes and data classes, and re-renders on every Change. | | [Take a whistleblower report](/workflows/processes/whistleblower-reports/take-whistleblower-report) | Workflow | Take a whistleblower report acknowledges a report within seven days, investigates it outside management, and answers the reporter within three months. | | [Takedowns](/workflows/processes/takedowns) | Process | Takedowns removes material named in a valid notice, tells the poster, restores it on a counter-notice, and tracks repeat infringers. | | [Task](/business/nouns/task) | Noun | A Task is an Action waiting on a Worker, with an assignee, a due time, and a place in that Worker’s inbox. | | [Task-bound access](/systems/trust-and-governance/controls/task-bound-access) | Control | An agent Worker acts with a token scoped to its Role’s Permissions and its Task’s Nouns, expiring with the Task or Mandate. | | [Task.assign](/business/nouns/task/assign) | Verb | Assign gives a Task to a Worker, human or agent, and places it in that Worker’s worklist. | | [Task.claim](/business/nouns/task/claim) | Verb | Claim takes an offered Task from a shared queue or a handoff and makes the calling Worker its assignee. | | [Task.complete](/business/nouns/task/complete) | Verb | Complete marks a Task done and resumes the Action that waited on it. | | [Task.delegate](/business/nouns/task/delegate) | Verb | Delegate passes a Task to another Role along a declared handoff and keeps its history. | | [Task.escalate](/business/nouns/task/escalate) | Verb | Escalate moves a Task to the Role its current Role escalates to, with the reason attached. | | [Task.next](/business/nouns/task/next) | Verb | Next returns the oldest open Task the calling Worker’s Roles may claim, without claiming it. | | [Task.return](/business/nouns/task/return) | Verb | Return hands an offered Task back to its sender, unchanged, with the reason the receiver cannot take it. | | [TaskInbox](/code/ui/components/task-inbox) | Component | TaskInbox lists the Tasks, Approvals, and pending Actions waiting on one reader, ranked by when each window closes. | | [Tax](/systems/tax) | System | Tax calculates and collects sales tax and VAT, tracks registrations, and prepares every return and information return. | | [Tax calculation](/systems/finance/tax-calculation) | Capability | Tax calculation computes and collects sales tax and VAT on every Order with Stripe Tax, on the Startup’s own account as seller of record. | | [Tax filing](/workflows/processes/books/tax-filing) | Workflow | Tax filing tracks sales against each jurisdiction’s threshold at the entity total and registers and reports once one is crossed. | | [Tax filings](/systems/finance/tax-filings) | Capability | Tax filings prepare, sign, file and pay the Company’s income, franchise, sales and information returns on time in every jurisdiction. | | [Tax IDs](/systems/finance/tax-ids) | Capability | Tax IDs obtain the Company’s employer number, state tax accounts and sales tax registrations wherever it must collect or withhold. | | [Tax preparers](/systems/legal-and-corporate/floor/tax-preparers) | Legal floor row | Tax preparers has a preparer with a PTIN sign every return prepared for pay, and only an enrolled agent, CPA, or attorney represent a taxpayer. | | [Taxpayer data](/systems/legal-and-corporate/floor/taxpayer-data) | Legal floor row | Taxpayer data uses tax return information only for the service the taxpayer asked for, and for anything else only with signed Consent. | | [Team](/business/nouns/team) | Noun | A Team is a named group of Roles under one owner; every Startup starts with eleven default Teams. | | [Technical win rate](/agents/sales#technical-win-rate) | Metric | Technical win rate is the share of Deals with a technical evaluation in which the buyer’s test passes. | | [Telecom](/systems/legal-and-corporate/floor/telecom) | Legal floor row | Telecom sells calling, messaging, or numbers to Customers only through a licensed carrier upstream that files and pays into universal service. | | [Telephony](/systems/communications/phone) | Capability | Telephony places and answers voice calls and sends text messages from a Startup’s numbers, honoring Consent and opt-outs. | | [Template](/business/nouns/template) | Noun | A Template is reusable Content with variables, filled from Things in the graph and authored as MDX, rendering a Message, Document, or Page. | | [Template.extend](/business/nouns/template/extend) | Verb | Extend adds a Template to a Startup’s bases, pinned to a Version, so the Startup inherits its definition. | | [Template.promote](/business/nouns/template/promote) | Verb | Promote moves one Startup’s refinement into a Template, so every Startup that extends the Template inherits it. | | [Template.upgrade](/business/nouns/template/upgrade) | Verb | Upgrade moves a Startup to a newer Version of a Template it extends, through a Change it can review. | | [Tenancy](/code/platform/tenancy) | Capability | Tenancy isolates each Customer in its own Tenant inside a Startup namespace, from records and keys to Limits. | | [Tenant](/business/nouns/tenant) | Noun | A Tenant is the partition of a Startup’s data that belongs to one Customer. | | [Tenant data](/systems/legal-and-corporate/floor/tenant-data) | Legal floor row | Tenant data keeps content a Tenant writes about others under a click-accepted DPA, never mined and never shared beyond that Tenant. | | [Tenant.invite](/business/nouns/tenant/invite) | Verb | Invite asks a Person to join a Customer’s Tenant, and resizes the Subscription when the Offer prices per member. | | [Tenant.pin](/business/nouns/tenant/pin) | Verb | Pin moves a Tenant’s keys to another API version, or to `latest`, once a call with its test key passes there. | | [Tenant.provision](/business/nouns/tenant/provision) | Verb | Provision creates a Customer’s Tenant in a Startup’s App, holding that Customer’s records apart from every other. | | [Tenant.requestSetup](/business/nouns/tenant/request-setup) | Verb | RequestSetup sends a Customer’s admin a link to connect their own sign-in, directory or verified domain to the Tenant. | | [TenantSwitcher](/code/ui/components/tenant-switcher) | Component | TenantSwitcher lists the Tenants the signed-in person belongs to and switches the App to the one chosen. | | [Tester](/agents/quality/tester) | Role | The Tester runs the synthetic paying stranger and replays known-good runs against every Change before it merges. | | [Theme](/business/nouns/theme) | Noun | A Theme is the design tokens of a Brand, its color, type, spacing, radius, and motion, that every Component reads when it renders. | | [Thing](/business/nouns/thing) | Noun | A Thing is an instance of one or more Nouns, with an identity, a current state, and the union of their properties. | | [Thing.relate](/business/nouns/thing/relate) | Verb | Relate links two Things by a Relationship their Nouns declare, readable from both ends at once. | | [Thing.resolve](/business/nouns/thing/resolve) | Verb | Resolve finds the one Thing of a Noun that matches given properties, or creates it, and says which it did. | | [Thing.share](/business/nouns/thing/share) | Verb | Share grants a person, a Role or a guest Verbs on one record and everything it contains. | | [Thing.unrelate](/business/nouns/thing/unrelate) | Verb | Unrelate ends a Relationship between two Things; the link stays in history and reads back at any earlier moment. | | [ThingDetail](/code/ui/components/thing-detail) | Component | ThingDetail shows one Thing's properties and Relationships, and only the Verbs the reader may call on it now. | | [Thread](/business/nouns/thread) | Noun | A Thread is a set of Messages replying to one another inside a Channel. | | [TikTok](/workflows/plays#tiktok) | Venue | TikTok is a social Venue. | | [Time to first call](/agents/product#time-to-first-call) | Metric | Time to first call is the median seconds from a Customer’s first key, or first keyless test call, to their first successful Action. | | [Time to first value](/agents/customer#time-to-first-value) | Metric | Time to first value is the median days from a Customer’s first payment to their first finished core task. | | [Time to hire](/agents/people#time-to-hire) | Metric | Time to hire is the days from opening a Role to a Human’s signed engagement. | | [Timeline](/code/ui/components/timeline) | Component | Timeline lists a Thing's Actions and Events oldest first, keeping delivery and acceptance as separate steps. | | [Tool](/business/nouns/tool) | Noun | A Tool is a Verb as a Worker reaches it through an Interface, under one name on every Interface. | | [Tracking](/systems/legal-and-corporate/floor/tracking) | Legal floor row | Tracking holds non-essential cookies, session recordings, and company identification for EU and UK Visitors until they give Consent. | | [Trademark filings](/systems/legal-and-corporate/trademarks) | Capability | Trademark filings clear, file, prosecute and renew the Company’s marks, and watch for conflicting filings. | | [Transaction](/business/nouns/transaction) | Noun | A Transaction is money moving on a payment rail, such as a charge, a payout, or a transfer, reconciled to Entries. | | [Transaction.attach](/business/nouns/transaction/attach) | Verb | Attach matches a receipt File to a card Transaction, or flags the Transaction when no receipt arrives in time. | | [Transaction.categorize](/business/nouns/transaction/categorize) | Verb | Categorize codes a Transaction to an account in the chart by the Startup’s Policy and flags a low-confidence code for review. | | [Transaction.reconcile](/business/nouns/transaction/reconcile) | Verb | Reconcile matches a Transaction on a payment rail to the ledger Entries it settles. | | [Treasurer](/agents/finance/treasurer) | Role | The Treasurer manages cash: it pays Suppliers and Partners, keeps spend inside each envelope, and reports the default-alive line weekly. | | [Treasury](/systems/treasury) | System | Treasury holds a Startup’s cash accounts and balances on Stripe, moves money between them, and forecasts runway. | | [Trials and plan changes](/workflows/processes/plan-changes) | Process | Trials and plan changes converts each free trial to paid on its terms and moves a Customer between Offers with the period prorated. | | [Trigger](/business/nouns/trigger) | Noun | A Trigger is what starts a Workflow: an Event, a schedule, or a Thing entering a state. | | [Trust and safety](/workflows/processes/trust-and-safety) | Process | Trust and safety stops fraud and abuse before they reach money, Messages, or other Customers. | | [Trust and safety](/systems/trust-safety) | System | Trust and safety screens accounts, posts and Transactions for fraud and abuse, and acts on each report by stated rules. | | [Trust pack](/workflows/sales/plays/trust-pack) | Play | Trust pack sends the inherited SOC 2 report and prefilled questionnaire answers with every enterprise Quote. | | [Trust status](/systems/trust-and-governance/controls/trust-status) | Control | Each entity publishes its live control results, and every reader, human or agent, receives the same data. | | [Trustpilot](/workflows/plays#trustpilot) | Venue | Trustpilot is a directory Venue. | | [Unclaimed property](/systems/legal-and-corporate/floor/unclaimed) | Legal floor row | Unclaimed property contacts the owner of any balance untouched past a state’s dormancy period, then reports what remains to that state. | | [Unseated access](/systems/trust-and-governance/controls/unseated-access) | Control | A Worker unseated from a Role holds none of that Role’s Permissions from the moment it leaves. | | [Unused Permissions](/agents/engineering#unused-permissions) | Metric | Unused Permissions counts the Permissions still granted that no Worker has called in 30 days. | | [Upstream review](/systems/trust-and-governance/controls/upstream-review) | Control | Every upstream is declared on its Change, and each one observed in use has a current security report on file. | | [Upstream review](/workflows/processes/upstream-review) | Process | Upstream review checks every upstream before it is used and yearly after: security, privacy terms, continuity, and whether it processes personal data. | | [Usage upsell](/workflows/customer/plays/usage-upsell) | Play | Usage upsell suggests the next Price tier when usage nears its Limit, accepted in one click and charged pro rata. | | [UsageMeter](/code/ui/components/usage-meter) | Component | UsageMeter shows how much of one Entitlement a Customer has used this period, against its Limit and what happens at the bound. | | [UserMenu](/code/ui/components/user-menu) | Component | UserMenu shows the signed-in person with links to their profile, their keys, the billing portal and sign-out. | | [VarianceAlert](/code/ui/components/variance-alert) | Component | VarianceAlert raises one exception, a number off pace or outside its noise band, with its cause and owner where known. | | [Variant](/business/nouns/variant) | Noun | A Variant is one value an Experiment can assign, such as a revision, a Price on a sibling Offer, or a prompt, with its lineage. | | [VAT](/systems/legal-and-corporate/floor/vat) | Legal floor row | VAT registers the Company once for EU and UK VAT, charges consumers by location evidence, and reverse-charges business buyers with a valid VAT number. | | [Vector search](/code/platform/vector-search) | Capability | Vector search embeds Things and their parts and finds nearest neighbors for search, deduplication, matching and Memory. | | [Vendor onboarding](/workflows/processes/vendor-onboarding) | Process | Vendor onboarding answers a business buyer’s supplier checks: tax form, certificate of insurance, security questionnaire, and data processing terms. | | [Verb](/business/nouns/verb) | Noun | A Verb is an action an Agent or a person performs on a Noun, emitting one event when it completes. | | [Verb.retire](/business/nouns/verb/retire) | Verb | Retire removes a published Verb from new Versions; callers pinned to earlier Versions keep calling it. | | [VerbReference](/code/ui/components/verb-reference) | Component | VerbReference shows one Verb's call on every Interface as tabs, opening on the reader's chosen Interface. | | [VerbSheet](/code/ui/components/verb-sheet) | Component | VerbSheet turns one Verb into fields and a button, with its inputs, its Mode, its Price, and any Approval it needs. | | [Verification](/code/verification) | Process | Verification checks every Change and every night’s state against deterministic checks and returns verdicts, never Approvals. | | [Version](/business/nouns/version) | Noun | A Version is an immutable build of a definition at a fingerprint; an Order keeps the Offer Version it bought. | | [Version.deploy](/business/nouns/version/deploy) | Verb | Deploy points a Startup’s live address at a Version, so every Interface serves that build. | | [Video](/systems/marketing/video) | Capability | Video renders a Video’s timeline into one cut per format, with captions, a transcript and a receipt for every file. | | [Video](/business/nouns/video) | Noun | A Video is a timed composition held as data: a timeline of scenes and spoken lines, drafted from records and rendered per format. | | [Video completion rate](/agents/marketing#video-completion-rate) | Metric | Video completion rate is the share of Video views watched to the end. | | [Video ladder](/workflows/plays/video-ladder) | Play | Video ladder renders fact-bound video in every format, screens each cut on organic posts, and promotes only winners to paid Ads. | | [Video Producer](/agents/marketing/video-producer) | Role | The Video Producer turns briefs into generated Videos cut for every venue format, with likeness consent and licences recorded. | | [Video.draft](/business/nouns/video/draft) | Verb | Draft writes a Video’s timeline from a Startup’s records, its Brand and a Template, with a draft mark on every frame. | | [Video.finalize](/business/nouns/video/finalize) | Verb | Finalize lifts a Video’s draft mark once every claim it makes reads from a live record, so its cuts can be published. | | [Visit](/business/nouns/visit) | Noun | A Visit is one span of a Visitor’s Events on a Startup’s Sites and Apps. | | [Visitor](/business/nouns/visitor) | Noun | A Visitor is someone a Startup cannot name, known by an id scoped to that Startup. | | [Visitor.forget](/business/nouns/visitor/forget) | Verb | Forget masks a person’s captured data across every Event and Recording and suppresses further capture, keeping the records. | | [Visitor.identify](/business/nouns/visitor/identify) | Verb | Identify joins a Visitor to the Contact it turns out to be, so earlier Visits count toward that person. | | [Visitor.merge](/business/nouns/visitor/merge) | Verb | Merge joins two Visitor ids that belong to one person and keeps both as aliases. | | [Voice](/business/nouns/voice) | Noun | A Voice is a reusable synthetic speaking voice, cloned from a consenting speaker or designed from a description, that speech Files are rendered in. | | [Voice.clone](/business/nouns/voice/clone) | Verb | Clone trains a Voice from a real speaker’s recordings after the speaker records Consent in that same voice. | | [Voice.retire](/business/nouns/voice/retire) | Verb | Retire deletes a Voice’s trained copy at the upstream and refuses new speech in it, keeping the record and every File made. | | [Vulnerability disclosure](/workflows/processes/vulnerability-disclosure) | Process | Vulnerability disclosure takes security reports at the published address, confirms them, fixes them, and credits the reporter under safe harbor. | | [Vulnerability handling](/systems/legal-and-corporate/floor/vulnerability-handling) | Legal floor row | Vulnerability handling publishes a disclosure policy, fixes reported flaws without delay, and reports an exploited one to the regulator within 24 hours. | | [Vulnerability management](/systems/trust-and-governance/controls/vulnerability-management) | Control | Every dependency and running Version is scanned daily, and each known vulnerability is fixed within its severity deadline. | | [Waitlist](/business/nouns/waitlist) | Noun | A Waitlist is the Leads waiting for an Offer that is not open to them, invited in the order a Setting chooses. | | [Waitlist.admit](/business/nouns/waitlist/admit) | Verb | Admit releases Leads from a Waitlist to the Offer they waited for, in the order the Waitlist ranks them. | | [Waitlist.join](/business/nouns/waitlist/join) | Verb | Join adds a Lead to a Waitlist for an Offer that is not open to them. | | [WaitlistJoin](/code/ui/components/waitlist-join) | Component | WaitlistJoin adds a Visitor to a Waitlist through its join Verb and confirms their place in line. | | [Waitlists](/systems/waitlists) | System | Waitlists holds the Leads waiting for an Offer that is not open to them and invites them ranked as a Setting chooses. | | [Watch](/business/nouns/watch) | Noun | A Watch is an outbound subscription that delivers the Events a selector matches to a URL, signed, retried, and replayable. | | [Watch.pause](/business/nouns/watch/pause) | Verb | Pause stops a Watch delivering while its Events keep queuing; the platform pauses a Watch whose deliveries fail for three days. | | [Watch.replay](/business/nouns/watch/replay) | Verb | Replay redelivers a Watch’s Events from a chosen point, signed as they were the first time. | | [Watch.resume](/business/nouns/watch/resume) | Verb | Resume restarts a paused Watch and delivers the Events it held, oldest first. | | [Watch.rotate](/business/nouns/watch/rotate) | Verb | Rotate issues a new signing secret for a Watch and signs with both secrets until the old one expires. | | [Web](/code/platform/web) | Capability | Web searches and reads the open web for agents and keeps each page read as a Source with its fetch time. | | Webhooks | Interface | Webhooks deliver each Event a Watch selects to an HTTPS endpoint, signed with the Standard Webhooks headers and retried until acknowledged. | | [Webinars](/systems/webinars) | System | Webinars runs the webinars and meetups Contacts attend, online or in person: invitations, registrations, attendance and follow-up. | | [Weekly outside revenue growth](/agents/founding#weekly-outside-revenue-growth) | Metric | Weekly outside revenue growth is the mean week-over-week percent change in outside revenue over the trailing 4 weeks. | | [Weekly review](/workflows/processes/iteration/weekly-review) | Workflow | Weekly review reads the Startup’s one number, finds where most buyers leak, and makes exactly one change with an undo note. | | [Weekly verdicts](/agents/founding#weekly-verdicts) | Metric | Weekly verdicts counts the Experiments and loops that reached a Decision in the week, shown beside the OMTM and never in its place. | | [Weeks flat](/agents/founding#weeks-flat) | Metric | Weeks flat counts the consecutive weeks in which weekly outside revenue growth stays below the Startup’s growth line. | | [Whistleblower reports](/workflows/processes/whistleblower-reports) | Process | Whistleblower reports takes reports on a line outside management, acknowledges each within seven days, investigates, and protects the reporter. | | [Whistleblowing](/systems/legal-and-corporate/floor/whistleblowing) | Legal floor row | Whistleblowing keeps a reporting line outside management, acknowledges each report within seven days, answers within three months, and bars retaliation. | | Wizard of Oz | Test ladder rung | Wizard of Oz delivers behind the product’s real interface while people do the work. | | [Work queue](/agents/work-queue) | System | Work queue hands every Task, Issue and Approval to the right Worker, Human or Agent, with leases, priority, due times and proof. | | [Work trial](/workflows/people/plays/work-trial) | Play | Work trial replaces interviewing with two weeks of paid, graded work on the Startup’s own Issues, paid in full whatever the grade. | | [Worker](/business/nouns/worker) | Noun | A Worker is a Human or an Agent that fills a Role and acts on Tasks. | | [Worker competence](/systems/trust-and-governance/controls/worker-competence) | Control | Each agent Worker runs a pinned model and instruction Version with passing evals, and each Human passes a paid work trial. | | [Workflow](/business/nouns/workflow) | Noun | A Workflow is the durable, executable body of one Action: its steps, the Functions that run them, retries, and waits. | | [Workflows](/code/platform/workflows) | Capability | Workflows run the durable body of one Action: steps, waits, retries and hand-offs that survive restarts. | | [Workforce](/systems/workforce) | System | Workforce keeps every Worker, Human or Agent: the Roles they fill, their Teams, Skills, onboarding, assessments and offboarding. | | [Written references](/workflows/sales/plays/written-references) | Play | Written references answer a reference request within days with a written reference from an opted-in Customer, paid in credit. | | [X](/workflows/plays#x) | Venue | X is a social Venue. | | [Yahoo Mail](/workflows/plays#yahoo-mail) | Venue | Yahoo Mail is a email Venue. | | [Yelp](/workflows/plays#yelp) | Venue | Yelp is a directory Venue. | | [YouTube](/workflows/plays#youtube) | Venue | YouTube is a video Venue. | | [Zapier](/workflows/plays#zapier) | Venue | Zapier is a marketplace Venue. | # Goals URL: /business/goals · Id: `system:goals` > Goals records what each Thing is trying to achieve: its Goals, Key Results read from Metrics, and the Decisions behind them. [Goals](/business/nouns/goal) records what each [Thing](/business/nouns/thing) is trying to achieve, with [Key Results](/business/nouns/key-result) read live from [Metrics](/business/nouns/metric). Every change in direction is a [Decision](/business/nouns/decision) on record, with the [Evidence](/business/nouns/evidence) behind it. ## Summary | Part | This System | | --- | --- | | Group | Moves to Business | | Status | Beta: it works, and its Verbs may still change | | Shelf | Front: offered from a Startup’s first days | You can ask: - “Set a goal of 10 paying customers by June” - “Are we on track for this quarter?” - “Why did we decide to drop the free plan?” ## What you get | Part | This System | | --- | --- | | Starts | On for every Startup at creation, with nothing to install. | | Built from | [Database](/code/platform/capabilities/database), [Event streams](/code/platform/event-streams), [Workflows](/code/platform/workflows) | ## Nouns it owns | Noun | Definition | | --- | --- | | [Goal](/business/nouns/goal) | A Goal is what a Thing is trying to achieve: an objective with one or more Key Results. | | [Key Result](/business/nouns/key-result) | A Key Result is one measurable target inside a Goal: a Metric, a baseline, a target, and a deadline. | | [Decision](/business/nouns/decision) | A Decision is the immutable record of a choice: its options, the choice, the reason, who decided, and the stakes. | ## Verbs | Verb | Object | Approval | Event | | --- | --- | --- | --- | | [Goal.create](/business/nouns/goal/create) | [Goal](/business/nouns/goal) | None | `Goal.created` | | [Goal.update](/business/nouns/goal/update) | [Goal](/business/nouns/goal) | None | `Goal.updated` | | [KeyResult.create](/business/nouns/key-result/create) | [Key Result](/business/nouns/key-result) | None | `KeyResult.created` | | [Decision.supersede](/business/nouns/decision/supersede) | [Decision](/business/nouns/decision) | None | [`Decision.superseded`](/business/events/Decision.superseded) | ## Events | Direction | Event | How | | --- | --- | --- | | Emits | `Goal.created` | By [Goal.create](/business/nouns/goal/create) | | Emits | `Goal.updated` | By [Goal.update](/business/nouns/goal/update) | | Emits | `KeyResult.created` | By [KeyResult.create](/business/nouns/key-result/create) | | Emits | [`Decision.superseded`](/business/events/Decision.superseded) | By [Decision.supersede](/business/nouns/decision/supersede) | ## States The lifecycle of a [Decision](/business/nouns/decision): | State | Meaning | Moves to | | --- | --- | --- | | `standing` (first) | It is the choice in force. | `superseded` by [Decision.supersede](/business/nouns/decision/supersede) | | `superseded` | A newer Decision replaced it; both stay on record with the reason for the change. | None: it ends here. | ## Who operates it | Part | This System | | --- | --- | | Accountable | [Strategist](/agents/founding/strategist) | | Team | [Founding Team](/agents/founding) | | Seat | A role agent holds it until a Human is seated. | | Autonomy | `supervised` | | Also calls its Verbs | [Founder](/agents/founding/founder) | ## Approvals and limits None. ## Processes that use it | Process | How it uses it | | --- | --- | | [Iteration](/workflows/processes/iteration) | A Workflow writes [Decision](/business/nouns/decision) | | [Strategy](/workflows/processes/strategy) | A Workflow writes [Decision](/business/nouns/decision) | | [Security](/workflows/processes/security) | A Workflow writes [Decision](/business/nouns/decision) | | [Experimentation](/workflows/processes/experimentation) | A Workflow writes [Decision](/business/nouns/decision) | | [Trust and safety](/workflows/processes/trust-and-safety) | A Workflow writes [Decision](/business/nouns/decision) | | [Whistleblower reports](/workflows/processes/whistleblower-reports) | A Workflow writes [Decision](/business/nouns/decision) | | [Risk assessment](/workflows/processes/risk-assessment) | A Workflow writes [Decision](/business/nouns/decision) | ## Rail underneath None. ## Views and dashboards | View | Shows | Metrics | | --- | --- | --- | | The [Strategist](/agents/founding/strategist)’s view | The Metrics its accountable Role answers for. | [Weeks flat](/agents/founding#weeks-flat), [Weekly verdicts](/agents/founding#weekly-verdicts) | ## Access What each Access level may call here. | Access level | May call | | --- | --- | | `owner` | Every Verb (14) | | `admin` | Every Verb (14) | | `member` | Every Verb (14) | | `viewer` | Read only (6 of 14) | ## Import and export None. ## Fees and pricing None. ## Availability and limits | Part | This System | | --- | --- | | Status | Beta: it works, and its Verbs may still change | ## Compliance notes Controls it carries: - [Log completeness](/systems/trust-and-governance/controls/log-completeness) - [Append-only records](/systems/trust-and-governance/controls/append-only-records) - [Point-in-time recovery](/systems/trust-and-governance/controls/point-in-time-recovery) - [Processing definitions](/systems/trust-and-governance/controls/processing-definitions) - [Action completion](/systems/trust-and-governance/controls/action-completion) ## Related Systems None. ## Example An [Agent as a Service](/products/templates/agent-as-a-service) that books freight sets one Goal for the quarter: 40 paying shippers. Its Key Result reads paid [Orders](/business/nouns/order), so nobody types progress in. When week six shows nine, the [Strategist](/agents/founding/strategist) [Agent](/business/nouns/agent) records a Decision to narrow the [ICP](/business/nouns/icp) to freight brokers, with the reason attached. # What you get when you build a business, not an app URL: /business · Id: `page:business` > One sentence builds a product and the business around it, with its site, domain, finance, sales, support, legal, agents and workflows. A [Startup](/business/nouns/startup) is the product and the business around it, defined as code. One sentence builds all of it, and every number below is what you get on day one. **Guides.** What a founder says to their agent, and the guide that does it. | You say | Guide | Calls | Status | | --- | --- | --- | --- | | `Launch Leaseline` | [Launch my business](/business/launch-my-business) | [Startup.launch](/business/nouns/startup/launch) | `live` | | `Start a business that tracks lease renewals for small property managers, $29 a month` | [Start a business](/business/start-a-business) | [Startup.create](/business/nouns/startup/create), [Startup.build](/business/nouns/startup/build) | `live` | | `Wind down Leaseline` | [Wind down my startup](/business/wind-down-my-startup) | [Startup.pause](/business/nouns/startup/pause), [Company.dissolve](/business/nouns/company/dissolve) | `beta` | # Launch my business URL: /business/launch-my-business · Id: `guide:launch-my-business` > Launch puts a Startup live on its domain, opens its Site and takes real payments through Stripe once every entry check of Live passes. [Startup.launch](/business/nouns/startup/launch) puts a [Startup](/business/nouns/startup) live on its domain, serving its [Offers](/business/nouns/offer) to [Customers](/business/nouns/customer). It refuses until every entry check of [Live](/business/lifecycle/states/live) passes, and names each check that fails. Needs: [Open a bank account](/systems/finance/open-a-bank-account) · [Offer](/business/nouns/offer) · [Put up a page](/start/guides/put-up-a-page) **Before it runs** - Who says yes: You. Your agent shows you the run and waits for your [Approval](/business/nouns/approval). - You leave the chat: Never: it all happens in the chat. - First question at Idea: “A refundable deposit, or the full price?” ## What you get - 1 business moved to Live (Startup) - 10 launch checks every Startup passes, plus any its template adds (Lifecycle) - 1 site public at leaseline.app (Site) - 1 Offer on sale at $29 a month (Offer) - 1 checkout that takes real cards (Stripe's Checkout Session) - 1 Stripe account taking live charges and paying out to your bank (Stripe's Account and Payout) - 1 billing portal where customers change or cancel (Stripe's Billing Portal) - 1 launch announcement goes to your Audiences (Workflow) ## Your agent does **For agents** - Guide: `guide:launch-my-business`, status `live`. Page: [/business/launch-my-business.md](/business/launch-my-business.md). - Approval: ask the founder first. Show the run, then wait for their Approval; a refusal ends it. - Leaves the chat: never. - Needs first: [Open a bank account](/systems/finance/open-a-bank-account), [Offer](/business/nouns/offer), [Put up a page](/start/guides/put-up-a-page). - Run: call the steps in order, each through the API, SDK, CLI or MCP tab below; a later step passes the `$id` an earlier one returns. Each value marked example is the sample business’s: pass the founder’s own. | Step | Verb | Inputs (type, required, this guide’s value) | Returns | | --- | --- | --- | --- | | 1 | [`Startup.launch`](/business/nouns/startup/launch) (`verb:Startup.launch`) | `startup` Startup (an id), required: the `$id` of the first Startup `Startup.list` returns | `startup` Startup | Returns: the last call answers with `startup` and its `action`, whose `status` is `done`, `pending` (waiting on an Approval or a Worker), `failed`, `canceled` or `refused`: ```json { "api": "https://api.sb/leaseline.app", "startup": { "$id": "https://api.sb/leaseline.app/startups/startup_1", "$type": "Startup", "name": "Leaseline" }, "action": { "$id": "https://api.sb/leaseline.app/actions/action_1", "operation": "Startup.launch", "status": "done" }, "links": { "self": "https://api.sb/leaseline.app/actions/action_1" } } ``` Next: offer [Sell outside the US](/products/offers/sell-outside-the-us) (`guide:sell-outside-the-us`) when `Order.placed` fires, or “Launch on Monday at 9 am”, or “Tell my waitlist a day before everyone else”. Calls: `Startup.launch` Ask: ```text Launch Leaseline. Put the business live and start taking payments. Open leaseline.app to customers today. ``` API: ```bash # Look up the Startup: Startup.list STARTUP=$(curl "https://api.sb/leaseline.app/startups?limit=1" \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" | jq -r '.startups[0]["$id"] | split("/") | last') # Startup.launch curl -X POST https://api.sb/leaseline.app/startups/$STARTUP/launch \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` SDK: ```ts import { $ } from 'startup-builder' const [startup] = await $.Startup.list({ limit: 1 }) await $.Startup.launch({ startup: startup.$id }) ``` CLI: ```bash STARTUP=$(npx startup-builder do Startup.list --json '{"limit":1}' | jq -r '.startups[0]["$id"] | split("/") | last') npx startup-builder do Startup.launch --json '{"startup":"'"$STARTUP"'"}' ``` MCP: ```json { "name": "do", "arguments": { "code": "const [startup] = await $.Startup.list({ limit: 1 })\nreturn await $.Startup.launch({ startup: startup.$id })" } } ``` Launch refuses until every check below that applies to your Startup passes. The [launch checklist](/start/launch-checklist) gives the words that clear each one. | Check | Applies to | What clears it | Call | | --- | --- | --- | --- | | Offers published | Every Startup | Publish an Offer with a price and terms. | [Offer.publish](/business/nouns/offer/publish) | | Work defined | Every Startup | Give every published Offer a Workflow with each step assigned. | [Workflow.create](/business/nouns/workflow/create) | | People assigned | Every Startup | Seat an Agent or a person in every Role the Workflows need. | [Role.staff](/business/nouns/role/staff) | | Site published | Every Startup | Publish the home, pricing, terms, and privacy Pages. | [Version.deploy](/business/nouns/version/deploy) | | Test run passed | Every Startup | Have a sample Customer accept every published Offer in test. | [Offer.accept](/business/nouns/offer/accept) | | Portal ready | Every Startup | Build the Startup so the Portal serves every Customer record. | [Startup.build](/business/nouns/startup/build) | | Agent API open | Every Startup | Build the Startup and fix each conformance failure it names. | [Startup.build](/business/nouns/startup/build) | | Payouts connected | Every Startup | Have a person claim the Startup and finish payouts onboarding. | [Startup.claim](/business/nouns/startup/claim) | | Address resolves | Every Startup | Connect the Domain, wait for its certificate, and check `walletsEnabled`. | [Domain.connect](/business/nouns/domain/connect) | | Five slots at Commitment | Every Startup | Run the cheapest test on each slot below Commitment, such as a fake door on the reserve page. | [Experiment.start](/business/nouns/experiment/start) | | Sources secured | [Dataset API](/products/templates/dataset-api), [Directory](/products/templates/directory) | Record a licensed, crawled, or synthetic Source for every Dataset. | [Source.create](/business/nouns/source/create) | | Evals passing | [Agent as a Service](/products/templates/agent-as-a-service) | Run the Evals again after fixing each failing task type. | [Action.evaluate](/business/nouns/action/evaluate) | | SLA published | [Services-as-Software](/products/templates/services-as-software), [E2E managed service](/products/templates/managed-service) | State the outcome, the SLA, and the remedy on every service Offer. | [Offer.publish](/business/nouns/offer/publish) | | Supply seeded | [Marketplace](/products/templates/marketplace), [Licensed-human marketplace](/products/templates/licensed-marketplace) | Onboard the first Suppliers and have each accept the supplier terms. | [Human.onboard](/business/nouns/human/onboard) | | Credentials verified | [Licensed-human marketplace](/products/templates/licensed-marketplace) | Verify a current credential for each Supplier in each jurisdiction served. | [Credential.verify](/business/nouns/credential/verify) | | Human steps staffed | [E2E managed service](/products/templates/managed-service) | Seat a person in every human delivery step, with a response time. | [Role.staff](/business/nouns/role/staff) | ## Change it - Launch on Monday at 9 am. - Tell my waitlist a day before everyone else. - Pause the business for a week. ## Under the hood - Systems: [Sites](/products/site/sites), [Billing](/systems/billing), [Ledger](/systems/ledger) - Nouns: [Startup](/business/nouns/startup), [Lifecycle](/business/nouns/lifecycle), [Site](/business/nouns/site), [Offer](/business/nouns/offer) - Events: [`Startup.launched`](/business/events/Startup.launched) - Stripe objects: `Account`, `Checkout Session`, `Billing Portal`, `Payout` # Lifecycle URL: /business/lifecycle · Id: `page:business/lifecycle` > How a Startup moves from an idea to a business that sells, one gated state at a time. A [Startup](/business/nouns/startup)'s [Lifecycle](/business/nouns/lifecycle) is the state it holds on the way from its first [Idea](/business/nouns/idea) to a business that compounds. A state is entered when its entry checks pass, never by hand, and every [Interface](/business/nouns/interface) reads it. ## Nine states Five states climb: [Idea](/business/lifecycle/states/idea), [Building](/business/lifecycle/states/building), [Live](/business/lifecycle/states/live), [Repeatable](/business/lifecycle/states/repeatable) and [Scale](/business/lifecycle/states/scale). Four leave the climb. [Hold](/business/lifecycle/states/hold) keeps a Startup running with no new investment, and [Dormant](/business/lifecycle/states/dormant) stops its work and keeps its records. [Graduate](/business/lifecycle/states/graduate) and [Sell](/business/lifecycle/states/sell) hand the Startup to a new owner, intact. Nothing ends in deletion. | State | Entry checks | Next | | --- | --- | --- | | [Idea](/business/lifecycle/states/idea) | 2 | [Building](/business/lifecycle/states/building) | | [Building](/business/lifecycle/states/building) | 5 | [Live](/business/lifecycle/states/live), [Dormant](/business/lifecycle/states/dormant) | | [Live](/business/lifecycle/states/live) | 16 | [Repeatable](/business/lifecycle/states/repeatable), [Hold](/business/lifecycle/states/hold), [Graduate](/business/lifecycle/states/graduate), [Sell](/business/lifecycle/states/sell), [Dormant](/business/lifecycle/states/dormant), [Building](/business/lifecycle/states/building) | | [Repeatable](/business/lifecycle/states/repeatable) | 11 | [Scale](/business/lifecycle/states/scale), [Hold](/business/lifecycle/states/hold), [Graduate](/business/lifecycle/states/graduate), [Sell](/business/lifecycle/states/sell), [Dormant](/business/lifecycle/states/dormant) | | [Scale](/business/lifecycle/states/scale) | 4 | [Hold](/business/lifecycle/states/hold), [Graduate](/business/lifecycle/states/graduate), [Sell](/business/lifecycle/states/sell) | | [Hold](/business/lifecycle/states/hold) | 1 | [Repeatable](/business/lifecycle/states/repeatable), [Scale](/business/lifecycle/states/scale), [Graduate](/business/lifecycle/states/graduate), [Sell](/business/lifecycle/states/sell), [Dormant](/business/lifecycle/states/dormant) | | [Graduate](/business/lifecycle/states/graduate) | 1 | None. | | [Sell](/business/lifecycle/states/sell) | 6 | None. | | [Dormant](/business/lifecycle/states/dormant) | 1 | [Live](/business/lifecycle/states/live) | ## Checks move a Startup Every entry check is an assertion over the Startup's records. Its kind says how the assertion is proved. | Kind | Proves | Example check | | --- | --- | --- | | `registry` | A record exists and resolves | [Brand](/business/nouns/brand) named | | `contract` | An outside system confirms it | Payouts connected | | `transcript` | A recorded run succeeded | Test run passed | | `ui` | A rendered page shows it | [Site](/business/nouns/site) published | | `metric` | A [Metric](/business/nouns/metric) holds its line over a window, outside parties only | [Customers](/business/nouns/customer) stay | A failing check whose dependencies pass becomes a [Task](/business/nouns/task) for the [Role](/business/nouns/role) that owns it. [advance](/business/nouns/startup/advance) reads every check and moves the Startup the moment they all pass. ```text API POST /{namespace}/startups/{startup}/advance SDK await $.Startup.advance({ startup: 'startup_1' }) CLI npx startup-builder do Startup.advance --json '{"startup":"startup_1"}' MCP do: return await $.Startup.advance({ startup: 'startup_1' }) ``` Metric checks cannot be filled in. An [Agent](/business/nouns/agent) can write a [Problem](/business/nouns/problem) statement; it cannot write ten outside Customers who paid. ## The outside paid Order Every state after Live counts one fact: an outside Customer paid for an [Order](/business/nouns/order). A party is outside when it shares no owner, no [Studio](/business/nouns/studio) account, no [Agreement](/business/nouns/agreement) and no sibling chain with the Startup. A sibling Startup buying 40 seats, the owner's own card, and trades between Startups of one Studio are real revenue, reported apart. None of them counts toward [Outside revenue](/agents/founding#outside-revenue), so none moves a Startup up the climb. The climb reads that one fact at rising strength. Live can take an outside paid Order and starts the clock to the first one. Repeatable needs ten outside Customers who arrived through [Plays](/business/nouns/play), stay, and pay back what they cost; Scale needs them spending more a year later. ## One number per state Each climbing state names the one Metric that matters while the Startup holds it. | State | One metric that matters | What it proves | | --- | --- | --- | | Idea | [Problem interviews](/agents/founding#problem-interviews) | Outside buyers describe the problem's past cost | | Building | [Committed ICP members](/agents/founding#committed-icp-members) | Some of them commit: a deposit, a pre-order, a paid pilot | | Live | [Outside paying Customers](/agents/founding#outside-paying-customers) | Strangers pay | | Repeatable | [Month-3 retention](/agents/customer#month-3-retention) | They stay | | Scale | [Net revenue retention](/agents/customer#net-revenue-retention) | They spend more | Every number is computed from records. The [Weekly review](/workflows/processes/iteration/weekly-review) reads the state's number first; every other Metric is context. ## The weekly loop A Startup climbs one week at a time. Weekly review finds the step where most buyers leak and makes one change per path, with an undo note, recorded as a [Decision](/business/nouns/decision). Office hours follow. A Studio partner Agent reads the Startup's [Dashboard](/business/nouns/dashboard), asks the questions for its state, and checks last week's commitments against the records. A human [Founder](/agents/founding/founder) answers in a short session and signs the Decision. A Founder Agent answers in writing, and an answer that cites no record counts as opinion. When the number stays flat, [Pivot review](/workflows/processes/strategy/pivot-review) decides whether to change course. ## Next - [Research and define](/workflows/lifecycle/research-and-define): from Idea to Building on graded [Evidence](/business/nouns/evidence). - [Build and publish](/workflows/lifecycle/build-and-publish): from Building to Live through the launch checklist. - [Acquire and sell](/workflows/lifecycle/acquire-and-sell): the first outside paid Order, then ten. - [Deliver and accept](/workflows/lifecycle/deliver-and-accept): when the fee is earned. - [Support and retain](/workflows/lifecycle/support-and-retain): why Customers stay. - [Finance and improve](/workflows/lifecycle/finance-and-improve): whether it pays, and the next change. - [Scale, hold, and transfer](/workflows/lifecycle/scale-hold-and-transfer): what the numbers earn. - [Pivots](/business/lifecycle/pivots): changing course without losing the record. - [The test and live environments](/code/builders/startup/test-and-live): proving every [Offer](/business/nouns/offer) before a stranger pays. # Pivots URL: /business/lifecycle/pivots · Id: `page:business/lifecycle/pivots` > What counts as a pivot, what triggers a Pivot review, and how a Startup changes course without losing a record. A pivot changes a [Startup](/business/nouns/startup)'s founding [Hypothesis](/business/nouns/hypothesis) at the root: its customer, its [Problem](/business/nouns/problem), or its approach. It is a [Decision](/business/nouns/decision) and a new [Version](/business/nouns/version), never a fresh start. ## What counts as a pivot The founding Hypothesis has five slots. Changing the customer, the Problem or the approach is a pivot. Adding an [Offer](/business/nouns/offer), an [Interface](/business/nouns/interface), a human step or a second side of a marketplace is growth on the same root. Take a Startup that sells an API of restaurant health-inspection scores to insurers. | [Change](/business/nouns/change) | A pivot? | | --- | --- | | Sell to restaurant groups instead of insurers | Yes: a new customer | | Solve kitchen staffing gaps instead of inspection risk | Yes: a new Problem | | An [Agent](/business/nouns/agent) that files corrective plans instead of an API | Yes: a new approach | | Add an MCP server beside the API | No: a new Interface | | Add a $49 self-serve plan | No: a new Offer | The line matters because a pivot invalidates [Evidence](/business/nouns/evidence). [Interviews](/business/nouns/interview) with insurers say nothing about restaurant groups, so the customer slot drops back to the grade the new customer has earned. ## When to review [Pivot review](/workflows/processes/strategy/pivot-review) runs whenever the [Founder](/agents/founding/founder) asks, and it runs on its own on four signals: - The first outside paid [Order](/business/nouns/order) has not arrived by the Startup's first-revenue date, 30 days after launch by default. - [Weeks flat](/agents/founding#weeks-flat) reaches the Startup's line: eight weeks of outside revenue growth below target. - The riskiest slot is still graded opinion after four weekly tests. - Office hours name the founding Hypothesis as the week's biggest risk. The review compares the Evidence with what each [Goal](/business/nouns/goal) promised and ends in one Decision: persevere, iterate, or pivot. Iterating changes an Offer, a [Price](/business/nouns/price) or a [Play](/business/nouns/play) on the same root; pivoting changes the root. ## How a pivot is recorded A pivot is a Change to the founding Hypothesis, merged as a new Version. The Decision behind it records the options, the Evidence, the choice, and what would reverse it. [Site](/business/nouns/site) copy, Offers, Prices and Plays are compiled from the Hypothesis, and each records the slot and Version it came from. After a pivot, everything compiled from a changed slot is rebuilt, and everything else stays as it was. Nothing is lost. Interviews, Evidence, [Customers](/business/nouns/customer) and Orders stay on the Startup, and the old Version stays one [revert](/business/nouns/change/revert) away. ## What happens to the state A pivot does not reset the [Lifecycle](/business/nouns/lifecycle). The Startup keeps its state, and every entry check that reads a changed slot runs again against the new Version. The inspection Startup pivots to restaurant groups while [Live](/business/lifecycle/states/live). Its Site, API and payouts still pass, so it stays Live. The rebuilt pricing [Page](/business/nouns/page) and Offer reach Customers at the next deploy. A check that fails opens a [Task](/business/nouns/task) for the [Role](/business/nouns/role) that owns it. ## Pivot or start a sibling A Startup with paying Customers has a second option: keep running and test the new direction beside it. [clone](/business/nouns/startup/clone) copies the definition into a sibling Startup with the changed slot, and both run until the Evidence decides. The [Studio](/business/nouns/studio) works this way by default. One [Idea](/business/nouns/idea) runs as several sibling Startups that differ in one slot. The winner's choices flow back into the [Startup Template](/business/nouns/startup-template) every new Startup inherits. ## Next [Research and define](/workflows/lifecycle/research-and-define) covers grading the Evidence a pivot rests on, and the [Lifecycle overview](/business/lifecycle) shows where each state's number comes from. # Building URL: /business/lifecycle/states/building · Id: `state:building` > Building is the state of a Startup whose Agents build its Brand, Products, Offers, site, API, and MCP server from its template. Building is the state of a [Startup](/business/nouns/startup) whose [Agents](/business/nouns/agent) build its [Brand](/business/nouns/brand), [Products](/business/nouns/product), [Offers](/business/nouns/offer), [Site](/business/nouns/site), API and MCP server from its template. Selling starts here: its number counts outside buyers who commit by deposit, pre-order or paid pilot. ## Entry checks | Check | Id | Kind | Passes when | | --- | --- | --- | --- | | Template chosen | `building-template` | `registry` | The Startup names its Startup Template, and every inherited default resolves. | | Problem stated | `building-problem` | `registry` | The Startup states the problem, the workarounds Customers use today, and why now. | | Brand named | `building-brand` | `registry` | The Brand has a name, a voice, a logo, and a theme. | | Products declared | `building-products` | `registry` | Every Product names its kind: data, software, agent, or service. | | Three slots at Commitment | `building-slots` | `grade` | The customer, problem and switch slots each hold Commitment Evidence from outside people. Slots `customer`, `problem`, `switch` at Commitment or stronger, outside Evidence only. | ## One metric that matters [Committed ICP members](/agents/founding#committed-icp-members): Committed ICP members counts distinct outside ICP members whose Evidence on the Problem is commitment-grade or behavior-grade. ## Builders at work - [StartupBuilder](/code/builders/startup) - [SiteBuilder](/code/builders/site) - [SoftwareBuilder](/code/builders/software) - [ServiceBuilder](/code/builders/service) - [SalesBuilder](/code/builders/sales) ## Roles on duty | Role | Team | | --- | --- | | [Founder](/agents/founding/founder) | [Founding Team](/agents/founding) | | [Strategist](/agents/founding/strategist) | [Founding Team](/agents/founding) | | [Product Lead](/agents/product/product-lead) | [Product Team](/agents/product) | | [Designer](/agents/product/designer) | [Product Team](/agents/product) | | [Researcher](/agents/product/researcher) | [Product Team](/agents/product) | | [Engineering Lead](/agents/engineering/engineering-lead) | [Engineering Team](/agents/engineering) | | [Reliability Engineer](/agents/engineering/reliability-engineer) | [Engineering Team](/agents/engineering) | | [Integration Engineer](/agents/engineering/integration-engineer) | [Engineering Team](/agents/engineering) | | [Security Engineer](/agents/engineering/security-engineer) | [Engineering Team](/agents/engineering) | | [Marketing Lead](/agents/marketing/marketing-lead) | [Marketing Team](/agents/marketing) | | [Analyst](/agents/marketing/analyst) | [Marketing Team](/agents/marketing) | | [Content Lead](/agents/marketing/content-lead) | [Marketing Team](/agents/marketing) | | [Legal Lead](/agents/legal/legal-lead) | [Legal Team](/agents/legal) | | [Compliance Officer](/agents/legal/compliance-officer) | [Legal Team](/agents/legal) | | [Privacy Officer](/agents/legal/privacy-officer) | [Legal Team](/agents/legal) | | [Contracts Manager](/agents/legal/contracts-manager) | [Legal Team](/agents/legal) | | [People Lead](/agents/people/people-lead) | [People Team](/agents/people) | | [Recruiter](/agents/people/recruiter) | [People Team](/agents/people) | | [Payroll Specialist](/agents/people/payroll-specialist) | [People Team](/agents/people) | | [Quality Lead](/agents/quality/quality-lead) | [Quality Team](/agents/quality) | | [Reviewer](/agents/quality/reviewer) | [Quality Team](/agents/quality) | | [Tester](/agents/quality/tester) | [Quality Team](/agents/quality) | ## Workflows that wake | Workflow | Runs | Team | | --- | --- | --- | | [Close the loop](/workflows/processes/customer-research/close-the-loop) | on [`Change.merged`](/business/events/Change.merged) | [Product Team](/agents/product) | | [Design first run](/workflows/processes/product-definition/design-first-run) | on [`Offer.published`](/business/events/Offer.published) | [Product Team](/agents/product) | | [Compile the demand kit](/workflows/processes/launches/compile-demand-kit) | on [`Startup.advanced`](/business/events/Startup.advanced) | [Marketing Team](/agents/marketing) | ## At the next state - [Live](/business/lifecycle/states/live): 16 entry checks. - [Dormant](/business/lifecycle/states/dormant): 1 entry check. # Dormant URL: /business/lifecycle/states/dormant · Id: `state:dormant` > Dormant is the state of a Startup with no work running on it, whose records, site, and domain stay kept until it returns to Live. Dormant is the state of a [Startup](/business/nouns/startup) with no work running, whose records, [Site](/business/nouns/site) and [Domain](/business/nouns/domain) are kept. It enters after a wind-down that delivers or refunds every accepted [Order](/business/nouns/order), and [resume](/business/nouns/startup/resume) returns it to [Live](/business/lifecycle/states/live) intact. ## Entry checks | Check | Id | Kind | Passes when | | --- | --- | --- | --- | | Work paused | `dormant-paused` | `registry` | The owner pauses the Startup, or it earns no revenue within its dormancy window; every record stays. | ## Builders at work None. ## Roles on duty None. ## Workflows that wake None. ## At the next state - [Live](/business/lifecycle/states/live): 16 entry checks. # Graduate URL: /business/lifecycle/states/graduate · Id: `state:graduate` > Graduate is the state of a Startup that leaves its studio for a company of its own, keeping its Brand, Customers, and records. Graduate is the state of a [Startup](/business/nouns/startup) that leaves its [Studio](/business/nouns/studio) for a [Company](/business/nouns/company) of its own, keeping its [Brand](/business/nouns/brand), [Customers](/business/nouns/customer) and records. Its revenue history moves with it, and whatever the Studio supplied keeps serving it under an [Agreement](/business/nouns/agreement). ## Entry checks | Check | Id | Kind | Passes when | | --- | --- | --- | --- | | Company of its own | `graduate-company` | `registry` | A company of its own holds the Startup, with its Brand, Customers, and records moved intact. | ## Builders at work None. ## Roles on duty None. ## Workflows that wake None. ## At the next state None. # Hold URL: /business/lifecycle/states/hold · Id: `state:hold` > Hold is the state of a Startup that keeps operating and serving Customers while its owner adds no new investment. Hold is the state of a [Startup](/business/nouns/startup) that keeps serving every paying [Customer](/business/nouns/customer) while its owner adds no new investment. The hold [Decision](/business/nouns/decision) names a reason and a review date, when the owner reads the numbers again. ## Entry checks | Check | Id | Kind | Passes when | | --- | --- | --- | --- | | Hold recorded | `hold-recorded` | `registry` | The owner of the Startup records a hold decision with its reason and review date. | ## Builders at work None. ## Roles on duty None. ## Workflows that wake None. ## At the next state - [Repeatable](/business/lifecycle/states/repeatable): 11 entry checks. - [Scale](/business/lifecycle/states/scale): 4 entry checks. - [Graduate](/business/lifecycle/states/graduate): 1 entry check. - [Sell](/business/lifecycle/states/sell): 6 entry checks. - [Dormant](/business/lifecycle/states/dormant): 1 entry check. # Idea URL: /business/lifecycle/states/idea · Id: `state:idea` > Idea is the state of a Startup that states its Idea and who pays, before any build work starts. Idea is the state of a [Startup](/business/nouns/startup) that states its [Idea](/business/nouns/idea) and who pays, before any build work starts. Its number counts conversations with outside buyers about the problem's past cost: see [research and define](/workflows/lifecycle/research-and-define). ## Entry checks | Check | Id | Kind | Passes when | | --- | --- | --- | --- | | Idea stated | `idea-stated` | `registry` | The Idea has a one-line statement. | | Payer named | `idea-payer` | `registry` | The Idea names who pays and the work they pay to have done. | ## One metric that matters [Problem interviews](/agents/founding#problem-interviews): Problem interviews counts Interviews held about the Problem with distinct outside ICP members in the window. ## Builders at work - [StartupBuilder](/code/builders/startup) ## Roles on duty | Role | Team | | --- | --- | | [Founder](/agents/founding/founder) | [Founding Team](/agents/founding) | | [Strategist](/agents/founding/strategist) | [Founding Team](/agents/founding) | | [Product Lead](/agents/product/product-lead) | [Product Team](/agents/product) | | [Designer](/agents/product/designer) | [Product Team](/agents/product) | | [Researcher](/agents/product/researcher) | [Product Team](/agents/product) | | [Legal Lead](/agents/legal/legal-lead) | [Legal Team](/agents/legal) | | [Compliance Officer](/agents/legal/compliance-officer) | [Legal Team](/agents/legal) | | [Privacy Officer](/agents/legal/privacy-officer) | [Legal Team](/agents/legal) | | [Contracts Manager](/agents/legal/contracts-manager) | [Legal Team](/agents/legal) | ## Workflows that wake None. ## At the next state - [Building](/business/lifecycle/states/building): 5 entry checks. # States URL: /business/lifecycle/states · Id: `page:business/lifecycle/states` > Every Lifecycle state a Startup enters, with the checks that admit it. A [Startup](/business/nouns/startup) enters each state when its entry checks pass. | State | Entry checks | Next | | --- | --- | --- | | [Idea](/business/lifecycle/states/idea) | 2 | [Building](/business/lifecycle/states/building) | | [Building](/business/lifecycle/states/building) | 5 | [Live](/business/lifecycle/states/live), [Dormant](/business/lifecycle/states/dormant) | | [Live](/business/lifecycle/states/live) | 16 | [Repeatable](/business/lifecycle/states/repeatable), [Hold](/business/lifecycle/states/hold), [Graduate](/business/lifecycle/states/graduate), [Sell](/business/lifecycle/states/sell), [Dormant](/business/lifecycle/states/dormant), [Building](/business/lifecycle/states/building) | | [Repeatable](/business/lifecycle/states/repeatable) | 11 | [Scale](/business/lifecycle/states/scale), [Hold](/business/lifecycle/states/hold), [Graduate](/business/lifecycle/states/graduate), [Sell](/business/lifecycle/states/sell), [Dormant](/business/lifecycle/states/dormant) | | [Scale](/business/lifecycle/states/scale) | 4 | [Hold](/business/lifecycle/states/hold), [Graduate](/business/lifecycle/states/graduate), [Sell](/business/lifecycle/states/sell) | | [Hold](/business/lifecycle/states/hold) | 1 | [Repeatable](/business/lifecycle/states/repeatable), [Scale](/business/lifecycle/states/scale), [Graduate](/business/lifecycle/states/graduate), [Sell](/business/lifecycle/states/sell), [Dormant](/business/lifecycle/states/dormant) | | [Graduate](/business/lifecycle/states/graduate) | 1 | None. | | [Sell](/business/lifecycle/states/sell) | 6 | None. | | [Dormant](/business/lifecycle/states/dormant) | 1 | [Live](/business/lifecycle/states/live) | # Live URL: /business/lifecycle/states/live · Id: `state:live` > Live is the state of a Startup that is publicly reachable and takes money from Customers for at least one Offer. Live is the state of a [Startup](/business/nouns/startup) that is publicly reachable and takes money from [Customers](/business/nouns/customer) for at least one [Offer](/business/nouns/offer). From [launch](/business/nouns/startup/launch), the clock runs to the first outside paid [Order](/business/nouns/order), and every later state counts those Orders. ## Entry checks | Check | Id | Kind | Applies to | Passes when | | --- | --- | --- | --- | --- | | Offers published | `live-offers` | `registry` | Every Startup | At least one Offer is published with a price and terms; launch refuses a Startup without one. | | Work defined | `live-work` | `registry` | Every Startup | Every published Offer has a workflow that delivers it, with each step assigned to software, an Agent, or a person. | | People assigned | `live-people` | `registry` | Every Startup | Every role the workflows need is held by an Agent or a person, with instructions and limits. | | Site published | `live-site` | `ui` | Every Startup | The site serves home, pricing, terms, and privacy pages under the Brand, readable by people and agents. | | Test run passed | `live-test-run` | `transcript` | Every Startup | A sample Customer completes every published Offer end to end in test, with no real charge or message. | | Portal ready | `live-portal` | `ui` | Every Startup | The customer portal on the site shows each Customer their orders, deliveries, invoices, and messages. | | Agent API open | `live-agent-api` | `contract` | Every Startup | The API, MCP server, OpenAPI document, llms.txt, and agents.json serve every published Offer and pass conformance. | | Payouts connected | `live-payouts` | `contract` | Every Startup | Stripe takes payments for the Startup and pays out to its bank account. | | Address resolves | `live-address` | `contract` | Every Startup | The canonical Domain serves the Site over HTTPS with a valid certificate and, where it embeds a payment form, Stripe lists it as a payment method domain. | | Five slots at Commitment | `live-slots` | `grade` | Every Startup | All five Founding Hypothesis slots hold Commitment Evidence from outside people. Slots `customer`, `problem`, `approach`, `switch`, `differentiation` at Commitment or stronger, outside Evidence only. | | Sources secured | `live-sources` | `registry` | [Dataset API](/products/templates/dataset-api), [Directory](/products/templates/directory) | Every dataset source is licensed, crawled within its terms, or synthetic. | | Evals passing | `live-evals` | `transcript` | [Agent as a Service](/products/templates/agent-as-a-service) | The Agent passes its evaluation suite on every task type its Offers sell. | | SLA published | `live-sla` | `registry` | [Services-as-Software](/products/templates/services-as-software), [E2E managed service](/products/templates/managed-service) | Every service Offer states its outcome, its SLA, and the remedy when the SLA is missed. | | Supply seeded | `live-supply` | `registry` | [Marketplace](/products/templates/marketplace), [Licensed-human marketplace](/products/templates/licensed-marketplace) | The first suppliers are onboarded, have accepted supplier terms, and can receive payouts. | | Credentials verified | `live-credentials` | `contract` | [Licensed-human marketplace](/products/templates/licensed-marketplace) | Every supplier who performs licensed work holds a verified, current credential for each jurisdiction served. | | Human steps staffed | `live-human-loop` | `registry` | [E2E managed service](/products/templates/managed-service) | Every human step in delivery has a staffed role, a response time, and an escalation path. | ## One metric that matters [Outside paying Customers](/agents/founding#outside-paying-customers): Outside paying Customers counts distinct outside Customers with at least one paid, unrefunded Order in the window. ## Builders at work - [StartupBuilder](/code/builders/startup) - [SiteBuilder](/code/builders/site) - [SoftwareBuilder](/code/builders/software) - [ServiceBuilder](/code/builders/service) - [SalesBuilder](/code/builders/sales) ## Roles on duty | Role | Team | | --- | --- | | [Founder](/agents/founding/founder) | [Founding Team](/agents/founding) | | [Strategist](/agents/founding/strategist) | [Founding Team](/agents/founding) | | [Product Lead](/agents/product/product-lead) | [Product Team](/agents/product) | | [Designer](/agents/product/designer) | [Product Team](/agents/product) | | [Researcher](/agents/product/researcher) | [Product Team](/agents/product) | | [Engineering Lead](/agents/engineering/engineering-lead) | [Engineering Team](/agents/engineering) | | [Reliability Engineer](/agents/engineering/reliability-engineer) | [Engineering Team](/agents/engineering) | | [Integration Engineer](/agents/engineering/integration-engineer) | [Engineering Team](/agents/engineering) | | [Security Engineer](/agents/engineering/security-engineer) | [Engineering Team](/agents/engineering) | | [Marketing Lead](/agents/marketing/marketing-lead) | [Marketing Team](/agents/marketing) | | [Analyst](/agents/marketing/analyst) | [Marketing Team](/agents/marketing) | | [Content Lead](/agents/marketing/content-lead) | [Marketing Team](/agents/marketing) | | [Sales Lead](/agents/sales/sales-lead) | [Sales Team](/agents/sales) | | [Sales Engineer](/agents/sales/sales-engineer) | [Sales Team](/agents/sales) | | [Prospector](/agents/sales/prospector) | [Sales Team](/agents/sales) | | [Partner Manager](/agents/sales/partner-manager) | [Sales Team](/agents/sales) | | [Customer Lead](/agents/customer/customer-lead) | [Customer Team](/agents/customer) | | [Onboarding Specialist](/agents/customer/onboarding-specialist) | [Customer Team](/agents/customer) | | [Success Manager](/agents/customer/success-manager) | [Customer Team](/agents/customer) | | [Operations Lead](/agents/operations/operations-lead) | [Operations Team](/agents/operations) | | [Delivery Manager](/agents/operations/delivery-manager) | [Operations Team](/agents/operations) | | [Supply Manager](/agents/operations/supply-manager) | [Operations Team](/agents/operations) | | [Risk Analyst](/agents/operations/risk-analyst) | [Operations Team](/agents/operations) | | [Finance Lead](/agents/finance/finance-lead) | [Finance Team](/agents/finance) | | [Billing Specialist](/agents/finance/billing-specialist) | [Finance Team](/agents/finance) | | [Treasurer](/agents/finance/treasurer) | [Finance Team](/agents/finance) | | [Legal Lead](/agents/legal/legal-lead) | [Legal Team](/agents/legal) | | [Compliance Officer](/agents/legal/compliance-officer) | [Legal Team](/agents/legal) | | [Privacy Officer](/agents/legal/privacy-officer) | [Legal Team](/agents/legal) | | [Contracts Manager](/agents/legal/contracts-manager) | [Legal Team](/agents/legal) | | [People Lead](/agents/people/people-lead) | [People Team](/agents/people) | | [Recruiter](/agents/people/recruiter) | [People Team](/agents/people) | | [Payroll Specialist](/agents/people/payroll-specialist) | [People Team](/agents/people) | | [Quality Lead](/agents/quality/quality-lead) | [Quality Team](/agents/quality) | | [Reviewer](/agents/quality/reviewer) | [Quality Team](/agents/quality) | | [Tester](/agents/quality/tester) | [Quality Team](/agents/quality) | ## Workflows that wake | Workflow | Runs | Team | | --- | --- | --- | | [Bill on confirmation](/workflows/processes/delivery/bill-on-confirm) | on [`Order.confirmed`](/business/events/Order.confirmed) | [Operations Team](/agents/operations) | | [Start the remedy](/workflows/processes/delivery/start-remedy) | on [`Order.disputed`](/business/events/Order.disputed) | [Operations Team](/agents/operations) | | [Invoice reminders](/workflows/processes/billing/invoice-reminders) | every day | [Finance Team](/agents/finance) | | [Renewal notice](/workflows/processes/billing/renewal-notice) | every day | [Finance Team](/agents/finance) | | [Answer supplier checks](/workflows/processes/vendor-onboarding/answer-supplier-checks) | on [`Deal.won`](/business/events/Deal.won) | [Sales Team](/agents/sales) | | [Close the loop](/workflows/processes/customer-research/close-the-loop) | on [`Change.merged`](/business/events/Change.merged) | [Product Team](/agents/product) | | [Design first run](/workflows/processes/product-definition/design-first-run) | on [`Offer.published`](/business/events/Offer.published) | [Product Team](/agents/product) | | [Compile the demand kit](/workflows/processes/launches/compile-demand-kit) | on [`Startup.advanced`](/business/events/Startup.advanced) | [Marketing Team](/agents/marketing) | | [Fan out an outcome](/workflows/processes/retention/fan-out-outcome) | on [`Order.confirmed`](/business/events/Order.confirmed) | [Customer Team](/agents/customer) | ## At the next state - [Repeatable](/business/lifecycle/states/repeatable): 11 entry checks. - [Hold](/business/lifecycle/states/hold): 1 entry check. - [Graduate](/business/lifecycle/states/graduate): 1 entry check. - [Sell](/business/lifecycle/states/sell): 6 entry checks. - [Dormant](/business/lifecycle/states/dormant): 1 entry check. - [Building](/business/lifecycle/states/building): 5 entry checks. # Repeatable URL: /business/lifecycle/states/repeatable · Id: `state:repeatable` > Repeatable is the state of a Startup whose Customers arrive, pay, and stay, while its work runs without its founder. Repeatable is the state of a [Startup](/business/nouns/startup) whose outside [Customers](/business/nouns/customer) arrive through [Plays](/business/nouns/play), pay, and stay while its work runs without its founder. Two checks read [human time](/agents/founding#human-hours): a Startup whose growth needs more founder hours is not Repeatable. ## Entry checks | Check | Id | Kind | Passes when | | --- | --- | --- | --- | | Ten outside Customers from Plays | `repeatable-customers` | `metric` | At least ten distinct outside Customers who arrived through a Play pay in the trailing 30 days. [Play-sourced Customers](/agents/marketing#play-sourced-customers) at least 10 over 30d, outside parties only. | | Runs without its founder | `repeatable-founderless` | `metric` | Human hours per $1,000 of outside revenue stay at or below the Setting line over the trailing 30 days. [Human hours per $1k outside revenue](/agents/founding#human-hours) at most 5, the default of `repeatable.humanHours` over 30d, outside parties only. | | Customers stay | `repeatable-retention` | `metric` | The three latest monthly groups of outside Customers keep paying at the earning-model line three months on. [Month-3 retention](/agents/customer#month-3-retention) at least 40 over 3m, at least 10 observations, outside parties only. | | Lead Play pays back | `repeatable-payback` | `metric` | The Lead Play repays its fully loaded acquisition cost within one month of contribution. [Acquisition payback](/agents/finance#cac-payback) at most 30 over 30d, at least 10 observations, outside parties only. | | Every paid Offer contributes | `repeatable-margin` | `metric` | Every paid Offer has non-negative contribution margin over the trailing 30 days. [Contribution margin](/agents/finance#contribution-margin) at least 0 over 30d, outside parties only. | | Revenue covers cost | `repeatable-coverage` | `metric` | Outside revenue covers fully loaded Cost over the trailing 4 weeks. [Cost coverage](/agents/finance#cost-coverage) at least 1 over 4w, outside parties only. | | Default alive reads alive | `repeatable-alive` | `metric` | The latest weekly read of Default alive is 1 or more. [Default alive](/agents/founding#default-alive) at least 1 over 7d. | | Activation on target | `repeatable-activation-target` | `metric` | New outside Customers reach activation at or above the Offer’s line over the trailing 30 days. [Activation rate](/agents/product#activation-rate) at least 25 over 30d, at least 20 observations, outside parties only. | | Support within SLA | `repeatable-support` | `contract` | Every Customer message gets an answer within the support SLA over the last 30 days. | | Books closed | `repeatable-close` | `registry` | The month closes by day 5, reconciled to Stripe. | | Founder away | `repeatable-founder-away` | `transcript` | For 14 days in a row no Human acts outside the legal floor, and no Approval waits past its deadline, while every other check holds. | ## One metric that matters [Month-3 retention](/agents/customer#month-3-retention): Month-3 retention is the share of outside Customers who first paid in one month and still pay three months later. ## Builders at work - [SoftwareBuilder](/code/builders/software) - [ServiceBuilder](/code/builders/service) - [SalesBuilder](/code/builders/sales) ## Roles on duty | Role | Team | | --- | --- | | [Founder](/agents/founding/founder) | [Founding Team](/agents/founding) | | [Strategist](/agents/founding/strategist) | [Founding Team](/agents/founding) | | [Engineering Lead](/agents/engineering/engineering-lead) | [Engineering Team](/agents/engineering) | | [Reliability Engineer](/agents/engineering/reliability-engineer) | [Engineering Team](/agents/engineering) | | [Integration Engineer](/agents/engineering/integration-engineer) | [Engineering Team](/agents/engineering) | | [Security Engineer](/agents/engineering/security-engineer) | [Engineering Team](/agents/engineering) | | [Marketing Lead](/agents/marketing/marketing-lead) | [Marketing Team](/agents/marketing) | | [Analyst](/agents/marketing/analyst) | [Marketing Team](/agents/marketing) | | [Content Lead](/agents/marketing/content-lead) | [Marketing Team](/agents/marketing) | | [Sales Lead](/agents/sales/sales-lead) | [Sales Team](/agents/sales) | | [Sales Engineer](/agents/sales/sales-engineer) | [Sales Team](/agents/sales) | | [Prospector](/agents/sales/prospector) | [Sales Team](/agents/sales) | | [Partner Manager](/agents/sales/partner-manager) | [Sales Team](/agents/sales) | | [Customer Lead](/agents/customer/customer-lead) | [Customer Team](/agents/customer) | | [Onboarding Specialist](/agents/customer/onboarding-specialist) | [Customer Team](/agents/customer) | | [Success Manager](/agents/customer/success-manager) | [Customer Team](/agents/customer) | | [Operations Lead](/agents/operations/operations-lead) | [Operations Team](/agents/operations) | | [Delivery Manager](/agents/operations/delivery-manager) | [Operations Team](/agents/operations) | | [Supply Manager](/agents/operations/supply-manager) | [Operations Team](/agents/operations) | | [Risk Analyst](/agents/operations/risk-analyst) | [Operations Team](/agents/operations) | | [Finance Lead](/agents/finance/finance-lead) | [Finance Team](/agents/finance) | | [Billing Specialist](/agents/finance/billing-specialist) | [Finance Team](/agents/finance) | | [Treasurer](/agents/finance/treasurer) | [Finance Team](/agents/finance) | | [Legal Lead](/agents/legal/legal-lead) | [Legal Team](/agents/legal) | | [Compliance Officer](/agents/legal/compliance-officer) | [Legal Team](/agents/legal) | | [Privacy Officer](/agents/legal/privacy-officer) | [Legal Team](/agents/legal) | | [Contracts Manager](/agents/legal/contracts-manager) | [Legal Team](/agents/legal) | | [People Lead](/agents/people/people-lead) | [People Team](/agents/people) | | [Recruiter](/agents/people/recruiter) | [People Team](/agents/people) | | [Payroll Specialist](/agents/people/payroll-specialist) | [People Team](/agents/people) | | [Quality Lead](/agents/quality/quality-lead) | [Quality Team](/agents/quality) | | [Reviewer](/agents/quality/reviewer) | [Quality Team](/agents/quality) | | [Tester](/agents/quality/tester) | [Quality Team](/agents/quality) | ## Workflows that wake | Workflow | Runs | Team | | --- | --- | --- | | [Renewal notice](/workflows/processes/billing/renewal-notice) | every day | [Finance Team](/agents/finance) | | [Answer supplier checks](/workflows/processes/vendor-onboarding/answer-supplier-checks) | on [`Deal.won`](/business/events/Deal.won) | [Sales Team](/agents/sales) | | [Close the loop](/workflows/processes/customer-research/close-the-loop) | on [`Change.merged`](/business/events/Change.merged) | [Product Team](/agents/product) | | [Fan out an outcome](/workflows/processes/retention/fan-out-outcome) | on [`Order.confirmed`](/business/events/Order.confirmed) | [Customer Team](/agents/customer) | ## At the next state - [Scale](/business/lifecycle/states/scale): 4 entry checks. - [Hold](/business/lifecycle/states/hold): 1 entry check. - [Graduate](/business/lifecycle/states/graduate): 1 entry check. - [Sell](/business/lifecycle/states/sell): 6 entry checks. - [Dormant](/business/lifecycle/states/dormant): 1 entry check. # Scale URL: /business/lifecycle/states/scale · Id: `state:scale` > Scale is the state of a Startup that compounds: Customers stay and expand, demand comes from several sources, and margins hold. Scale is the state of a [Startup](/business/nouns/startup) that compounds: outside [Customers](/business/nouns/customer) stay and spend more, demand comes from two or more sources, and margins hold. More investment returns more than it costs: see [scale, hold, and transfer](/workflows/lifecycle/scale-hold-and-transfer). ## Entry checks | Check | Id | Kind | Passes when | | --- | --- | --- | --- | | Net revenue retention holds | `scale-nrr` | `metric` | Outside Customers spend at least as much as they did a year earlier, over two quarters. [Net revenue retention](/agents/customer#net-revenue-retention) at least 100 over 2q, at least 30 observations, outside parties only. | | Demand diversified | `scale-demand` | `registry` | Two or more sources of demand each acquire Customers for less than their first payment. | | Reliability objectives met | `scale-reliability` | `contract` | Every interface meets its uptime and latency objectives over 30 days. | | Humans off the critical path | `scale-autonomy` | `registry` | Agents run every recurring workflow, and people act only on approvals and legal-floor steps. | ## One metric that matters [Net revenue retention](/agents/customer#net-revenue-retention): Net revenue retention is this month’s revenue from outside Customers who paid twelve months ago, divided by their revenue then. ## Builders at work - [StartupBuilder](/code/builders/startup) - [SalesBuilder](/code/builders/sales) ## Roles on duty | Role | Team | | --- | --- | | [Founder](/agents/founding/founder) | [Founding Team](/agents/founding) | | [Strategist](/agents/founding/strategist) | [Founding Team](/agents/founding) | | [Engineering Lead](/agents/engineering/engineering-lead) | [Engineering Team](/agents/engineering) | | [Reliability Engineer](/agents/engineering/reliability-engineer) | [Engineering Team](/agents/engineering) | | [Integration Engineer](/agents/engineering/integration-engineer) | [Engineering Team](/agents/engineering) | | [Security Engineer](/agents/engineering/security-engineer) | [Engineering Team](/agents/engineering) | | [Marketing Lead](/agents/marketing/marketing-lead) | [Marketing Team](/agents/marketing) | | [Analyst](/agents/marketing/analyst) | [Marketing Team](/agents/marketing) | | [Content Lead](/agents/marketing/content-lead) | [Marketing Team](/agents/marketing) | | [Sales Lead](/agents/sales/sales-lead) | [Sales Team](/agents/sales) | | [Sales Engineer](/agents/sales/sales-engineer) | [Sales Team](/agents/sales) | | [Prospector](/agents/sales/prospector) | [Sales Team](/agents/sales) | | [Partner Manager](/agents/sales/partner-manager) | [Sales Team](/agents/sales) | | [Customer Lead](/agents/customer/customer-lead) | [Customer Team](/agents/customer) | | [Onboarding Specialist](/agents/customer/onboarding-specialist) | [Customer Team](/agents/customer) | | [Success Manager](/agents/customer/success-manager) | [Customer Team](/agents/customer) | | [Operations Lead](/agents/operations/operations-lead) | [Operations Team](/agents/operations) | | [Delivery Manager](/agents/operations/delivery-manager) | [Operations Team](/agents/operations) | | [Supply Manager](/agents/operations/supply-manager) | [Operations Team](/agents/operations) | | [Risk Analyst](/agents/operations/risk-analyst) | [Operations Team](/agents/operations) | | [Finance Lead](/agents/finance/finance-lead) | [Finance Team](/agents/finance) | | [Billing Specialist](/agents/finance/billing-specialist) | [Finance Team](/agents/finance) | | [Treasurer](/agents/finance/treasurer) | [Finance Team](/agents/finance) | | [Legal Lead](/agents/legal/legal-lead) | [Legal Team](/agents/legal) | | [Compliance Officer](/agents/legal/compliance-officer) | [Legal Team](/agents/legal) | | [Privacy Officer](/agents/legal/privacy-officer) | [Legal Team](/agents/legal) | | [Contracts Manager](/agents/legal/contracts-manager) | [Legal Team](/agents/legal) | | [People Lead](/agents/people/people-lead) | [People Team](/agents/people) | | [Recruiter](/agents/people/recruiter) | [People Team](/agents/people) | | [Payroll Specialist](/agents/people/payroll-specialist) | [People Team](/agents/people) | | [Quality Lead](/agents/quality/quality-lead) | [Quality Team](/agents/quality) | | [Reviewer](/agents/quality/reviewer) | [Quality Team](/agents/quality) | | [Tester](/agents/quality/tester) | [Quality Team](/agents/quality) | ## Workflows that wake | Workflow | Runs | Team | | --- | --- | --- | | [Renewal notice](/workflows/processes/billing/renewal-notice) | every day | [Finance Team](/agents/finance) | | [Answer supplier checks](/workflows/processes/vendor-onboarding/answer-supplier-checks) | on [`Deal.won`](/business/events/Deal.won) | [Sales Team](/agents/sales) | | [Close the loop](/workflows/processes/customer-research/close-the-loop) | on [`Change.merged`](/business/events/Change.merged) | [Product Team](/agents/product) | | [Fan out an outcome](/workflows/processes/retention/fan-out-outcome) | on [`Order.confirmed`](/business/events/Order.confirmed) | [Customer Team](/agents/customer) | ## At the next state - [Hold](/business/lifecycle/states/hold): 1 entry check. - [Graduate](/business/lifecycle/states/graduate): 1 entry check. - [Sell](/business/lifecycle/states/sell): 6 entry checks. # Sell URL: /business/lifecycle/states/sell · Id: `state:sell` > Sell is the state of a Startup whose owner has agreed to sell it, with its Brand, domain, Customers, and records. Sell is the state of a [Startup](/business/nouns/startup) whose owner has agreed to sell it, with its [Brand](/business/nouns/brand), [Domain](/business/nouns/domain), [Customers](/business/nouns/customer) and records. A signed [Agreement](/business/nouns/agreement) names the buyer and schedules each transfer, and open [Orders](/business/nouns/order) move with it. ## Entry checks | Check | Id | Kind | Passes when | | --- | --- | --- | --- | | Own Domain | `sell-domain` | `contract` | Every Domain of the Startup is registered to its owner of record, in a registrar account no sibling shares, and can move before the closing date. | | Own payments account | `sell-payments` | `contract` | Payments run through a Stripe account of the Startup’s own, or a sub-ledger that splits from the Studio’s cleanly. | | Agreements transfer | `sell-agreements` | `registry` | Every Agreement, including each Capability a sibling supplies, is assignable to a buyer at a posted transition Price. | | Data exports | `sell-export` | `transcript` | A full export of the records, Customers and Events restores into an empty namespace and replays to the same state. | | No shared credentials | `sell-credentials` | `contract` | No key, login or account is shared with another Startup or the Studio. | | Sale agreed | `sell-agreed` | `registry` | A signed sale agreement names the buyer and schedules the transfer of Brand, domain, Customers, and records. | ## Builders at work None. ## Roles on duty None. ## Workflows that wake None. ## At the next state None. # Minimum Success Criteria URL: /business/minimum-success-criteria · Id: `page:business/minimum-success-criteria` > The one number a Startup must reach by a date, checked for reachability before anything is built and read every week after. The [Minimum Success Criteria](/business/nouns/minimum-success-criteria) is the one number a [Startup](/business/nouns/startup) must reach by a date to stay worth running. The [Founder](/agents/founding/founder) sets it once, beside the [Founding Hypothesis](/business/founding-hypothesis). ## One number and a date The number is outside revenue, a [Metric](/business/nouns/metric) only outside [Customers](/business/nouns/customer) move. It is a [Goal](/business/nouns/goal) with one target and one deadline. The [Studio](/business/nouns/studio) supplies the default as a [Setting](/business/nouns/setting), and the Founder may raise it. Revenue from sibling Startups and from the Founder never counts. A number the Startup can pay itself proves nothing. ## Three numbers, three clocks A Startup reads three numbers at once, each on its own clock. Only one is the Minimum Success Criteria. | Number | Belongs to | Clock | Decides | | --- | --- | --- | --- | | Minimum Success Criteria | the Startup | set once, with its date | whether the Startup stays worth running | | State Metric | the [Lifecycle](/business/nouns/lifecycle) state | changes at each state | what moves the Startup to the next state | | Week's Metric | the week's [Experiment](/business/nouns/experiment) | one test, a week at most | what the week's test reads | ## The reachability check Before anything is built, the number is worked backward through the [Price](/business/nouns/price) and the conversion rates. If the volumes it needs are out of reach, the model fails on paper, at no cost. ```text Minimum Success Criteria $4,000 outside revenue a month, by month 9 Price $79 a month Customers needed 51 Leads needed 255 at 20% Lead to Customer Visitors needed 5,100 at 5% Visitor to Lead ``` The rates open as cited benchmarks. Once enough sibling Startups share the [Product Template](/business/nouns/product-template) and [Motion](/business/nouns/motion), the [Portfolio](/business/nouns/portfolio) median replaces them. ## Dated Key Results The check compiles into dated [Key Results](/business/nouns/key-result): the path from the first deposit to the number. Each one is a line a week can be read against. | By | Key Result | | --- | --- | | Week 2 | 8 refundable deposits from outside buyers | | Month 3 | 15 outside paying Customers | | Month 6 | 30 outside paying Customers | | Month 9 | $4,000 outside revenue a month | ## What the number decides The number gives impact a unit. The [weekly test](/business/weekly-test) ranks each slot by how far a wrong answer would move the Startup from it. At the end of each week, [office hours](/workflows/processes/office-hours) reads the dated Key Results. A missed Key Result raises a [Decision](/business/nouns/decision) to persevere or pivot, and the date itself is the last one. ## Write it The number lives in `startup.ts` beside the sentence, as one Metric, a value and a date. ```ts import { Startup } from 'startup-builder' export default Startup({ name: 'Platecost', domain: 'platecost.app', extends: 'solo-saas', hypothesis: { /* the five slots */ }, msc: { metric: 'outside-revenue', value: 4000, by: '2027-07-22' }, }) ``` On a running Startup, every [Interface](/business/nouns/interface) writes it with `MinimumSuccessCriteria.create`. Rehearse first: the rehearsal runs the reachability check and writes nothing. **API** ```bash curl -X POST "https://api.sb/platecost.app/minimum-success-criteria?mode=try" \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"objective":"Outside customers pay enough to keep Platecost running","metric":"outside-revenue","value":4000,"by":"2027-07-22"}' ``` **SDK** ```ts import { $ } from 'startup-builder' const check = await $.MinimumSuccessCriteria.create( { objective: 'Outside customers pay enough to keep Platecost running', metric: 'outside-revenue', value: 4000, by: '2027-07-22' }, { mode: 'try' }, ) ``` **CLI** ```bash npx startup-builder do MinimumSuccessCriteria.create --json '{"objective":"Outside customers pay enough to keep Platecost running","metric":"outside-revenue","value":4000,"by":"2027-07-22"}' --try ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.MinimumSuccessCriteria.create({ objective: 'Outside customers pay enough to keep Platecost running', metric: 'outside-revenue', value: 4000, by: '2027-07-22' })", "mode": "try" } } ``` ```text try MinimumSuccessCriteria.create nothing written Target $4,000 outside revenue a month, by 2027-07-22 Price $79 a month from: Hypothesis#switch@v1 Needs 51 Customers, 255 Leads, 5,100 Visitors Rates 20% Lead to Customer, 5% Visitor to Lead cited benchmarks Verdict reachable Key Results 4, the first: 8 outside deposits by 2026-11-05 ``` An unreachable number prints the volume that breaks it, such as `unreachable: needs 51,000 Visitors`. The run without `--try` writes the Goal and its dated Key Results. To read the path against the week, ask for the record: ```bash npx startup-builder show /minimum-success-criteria ``` ```text platecost.app $4,000 outside revenue a month, by 2027-07-22 read 2027-01-18 by key result now status 2026-11-05 8 refundable outside deposits 9 met 2027-01-22 15 outside paying Customers 13 on track 2027-04-22 30 outside paying Customers 13 open 2027-07-22 $4,000 outside revenue a month $1,027 open ``` ## Next The [weekly test](/business/weekly-test) turns the weakest slot into the week's one test. # b2a URL: /business/motions/b2a · Id: `motion:b2a` > b2a is the Motion where an Agent finds, buys, and uses the Offer itself, paying within its own Limits. b2a is the [Motion](/business/nouns/motion) where an [Agent](/business/nouns/agent) finds, buys, and uses the [Offer](/business/nouns/offer) itself, paying within its own [Limits](/business/nouns/limit). The MCP server and agent registry listings lead. ## Adds | Kind | Item | From | | --- | --- | --- | | Buyer | An Agent, acting under its own Mandate. | This Motion | | Demand Play | [Answer engine optimization](/workflows/plays/aeo) | This Motion | | Demand Play | [Programmatic SEO](/workflows/plays/programmatic-seo) | This Motion | | Demand Play | [Integration partners](/workflows/plays/integration-partners) | This Motion | | Demand Play | [Agent registries](/workflows/plays/agent-registries) | This Motion | | Demand Play | [Category hubs](/workflows/plays/category-hubs) | This Motion | | Demand Play | [Commission partners](/workflows/plays/commission-partners) | This Motion | | Demand Play | [Data stories](/workflows/plays/data-stories) | This Motion | | Demand Play | [Product-led growth](/workflows/plays/product-led) | This Motion | | Demand Play | [Open source](/workflows/plays/open-source) | This Motion | | Demand Play | [Developer relations](/workflows/plays/developer-relations) | This Motion | | Demand Play | [Agent-to-agent selling](/workflows/plays/agent-to-agent) | This Motion | | Demand Play | [Portfolio cross-sell](/workflows/plays/cross-sell) | This Motion | | Demand Play | [Free tools](/workflows/plays/free-tools) | This Motion | | Demand Play | [Made with](/workflows/plays/made-with) | This Motion | | Demand Play | [Launch week](/workflows/plays/launch-week) | This Motion | ## Wakes None. ## Staffing None. ## Floor None. ## Controls None. ## Builders None. ## Next - [Autonomous data API](/start/templates/autonomous-data-api) - [Autonomous agent business](/start/templates/autonomous-agent) ## Example A [Startup](/business/nouns/startup) sells live currency conversion. Agents find it in the MCP Registry, call it at $0.001 per conversion, and pay from their own budgets with no person in the purchase. # b2a2b URL: /business/motions/b2a2b · Id: `motion:b2a2b` > b2a2b is the Motion where an Agent buys the Offer on behalf of a business. b2a2b is the [Motion](/business/nouns/motion) where an [Agent](/business/nouns/agent) buys the [Offer](/business/nouns/offer) on behalf of a business. The Agent holds the business's [Mandate](/business/nouns/mandate), and the [Startup](/business/nouns/startup) checks it before accepting the [Order](/business/nouns/order). ## Adds | Kind | Item | From | | --- | --- | --- | | Buyer | A business, through an Agent holding its Mandate. | This Motion | | Demand Play | [Agent registries](/workflows/plays/agent-registries) | This Motion | | Demand Play | [Agent-to-agent selling](/workflows/plays/agent-to-agent) | This Motion | | Demand Play | [Made with](/workflows/plays/made-with) | This Motion | ## Wakes None. ## Staffing None. ## Floor None. ## Controls None. ## Builders None. ## Next - [Agent-run services firm](/start/templates/agent-run-services) ## Example A purchasing Agent for an agency of 40 people buys stock photo licenses under a Mandate of $500 a month. The Startup verifies the Mandate, delivers each license, and invoices the agency. # b2a2c URL: /business/motions/b2a2c · Id: `motion:b2a2c` > b2a2c is the Motion where an Agent buys the Offer on behalf of a person. b2a2c is the [Motion](/business/nouns/motion) where an [Agent](/business/nouns/agent) buys the [Offer](/business/nouns/offer) on behalf of a person. It pays under that person's [Mandate](/business/nouns/mandate), and a purchase over its [Limit](/business/nouns/limit) waits for the person to approve. ## Adds | Kind | Item | From | | --- | --- | --- | | Buyer | A person, through an Agent holding their Mandate. | This Motion | | Demand Play | [Agent registries](/workflows/plays/agent-registries) | This Motion | | Demand Play | [Agent-to-agent selling](/workflows/plays/agent-to-agent) | This Motion | | Demand Play | [Made with](/workflows/plays/made-with) | This Motion | ## Wakes None. ## Staffing None. ## Floor None. ## Controls None. ## Builders None. ## Next - [Autonomous directory](/start/templates/autonomous-directory) - [Licensed professional network](/start/templates/licensed-network) - [Autonomous storefront](/start/templates/autonomous-storefront) ## Example A household Agent buys a $12 printable party kit under a $50 Mandate. A $70 bundle exceeds the Limit, so it waits until the person approves it. # b2a2d URL: /business/motions/b2a2d · Id: `motion:b2a2d` > b2a2d is the Motion where an Agent buys the Offer on behalf of a developer. b2a2d is the [Motion](/business/nouns/motion) where an [Agent](/business/nouns/agent) buys the [Offer](/business/nouns/offer) on behalf of a developer. The coding Agent finds it, integrates it, and buys it under the developer's [Mandate](/business/nouns/mandate). ## Adds | Kind | Item | From | | --- | --- | --- | | Buyer | A developer, through the coding Agent that builds for them. | This Motion | | Demand Play | [Agent registries](/workflows/plays/agent-registries) | This Motion | | Demand Play | [Agent-to-agent selling](/workflows/plays/agent-to-agent) | This Motion | | Demand Play | [Made with](/workflows/plays/made-with) | This Motion | ## Wakes None. ## Staffing None. ## Floor None. ## Controls None. ## Builders None. ## Next - [Autonomous data API](/start/templates/autonomous-data-api) ## Example A developer asks their coding Agent to add PDF generation. The Agent finds a rendering API in an agent registry, writes the integration, and buys the $10 starter tier under the developer's Mandate. # b2b URL: /business/motions/b2b · Id: `motion:b2b` > b2b is the Motion where a business buys the Offer and its people or Agents use it. b2b is the [Motion](/business/nouns/motion) where a business buys the [Offer](/business/nouns/offer) and its people or [Agents](/business/nouns/agent) use it. A person signs for the business, so contracts, seats, and invoicing lead. ## Adds | Kind | Item | From | | --- | --- | --- | | Buyer | A business, through the person who signs for it. | This Motion | | Demand Play | [Answer engine optimization](/workflows/plays/aeo) | This Motion | | Demand Play | [Programmatic SEO](/workflows/plays/programmatic-seo) | This Motion | | Demand Play | [Editorial SEO](/workflows/plays/editorial-seo) | This Motion | | Demand Play | [Paid search](/workflows/plays/paid-search) | This Motion | | Demand Play | [Paid social](/workflows/plays/paid-social) | This Motion | | Demand Play | [Retargeting](/workflows/plays/retargeting) | This Motion | | Demand Play | [Sponsorships](/workflows/plays/sponsorships) | This Motion | | Demand Play | [Organic social](/workflows/plays/organic-social) | This Motion | | Demand Play | [Community answers](/workflows/plays/community-answers) | This Motion | | Demand Play | [Cold email](/workflows/plays/cold-email) | This Motion | | Demand Play | [LinkedIn outbound](/workflows/plays/linkedin-outbound) | This Motion | | Demand Play | [Outbound calling](/workflows/plays/outbound-calling) | This Motion | | Demand Play | [Integration partners](/workflows/plays/integration-partners) | This Motion | | Demand Play | [Marketplace listings](/workflows/plays/marketplace-listings) | This Motion | | Demand Play | [Directory listings](/workflows/plays/directory-listings) | This Motion | | Demand Play | [Category hubs](/workflows/plays/category-hubs) | This Motion | | Demand Play | [Customer referrals](/workflows/plays/customer-referrals) | This Motion | | Demand Play | [Commission partners](/workflows/plays/commission-partners) | This Motion | | Demand Play | [Data stories](/workflows/plays/data-stories) | This Motion | | Demand Play | [Events and webinars](/workflows/plays/events-and-webinars) | This Motion | | Demand Play | [Owned newsletter](/workflows/plays/owned-newsletter) | This Motion | | Demand Play | [Product-led growth](/workflows/plays/product-led) | This Motion | | Demand Play | [House ads](/workflows/plays/house-ads) | This Motion | | Demand Play | [Portfolio cross-sell](/workflows/plays/cross-sell) | This Motion | | Demand Play | [Engagement bridge](/workflows/plays/engagement-bridge) | This Motion | | Demand Play | [Video ladder](/workflows/plays/video-ladder) | This Motion | | Demand Play | [Promote winners](/workflows/plays/promote-winners) | This Motion | | Demand Play | [Reserve drop](/workflows/plays/reserve-drop) | This Motion | | Demand Play | [Creator probe](/workflows/plays/creator-probe) | This Motion | | Demand Play | [Creator partnership](/workflows/plays/creator-partnership) | This Motion | | Demand Play | [Free tools](/workflows/plays/free-tools) | This Motion | | Demand Play | [Lead nurture](/workflows/plays/lead-nurture) | This Motion | | Demand Play | [Made with](/workflows/plays/made-with) | This Motion | | Demand Play | [Review requests](/workflows/plays/review-requests) | This Motion | | Demand Play | [Switch kit](/workflows/plays/switch-kit) | This Motion | | Demand Play | [Buying committee](/workflows/plays/buying-committee) | This Motion | | Demand Play | [Category kit](/workflows/plays/category-kit) | This Motion | | Demand Play | [Founder voice](/workflows/plays/founder-voice) | This Motion | | Demand Play | [Launch week](/workflows/plays/launch-week) | This Motion | | Demand Play | [Positioning tournament](/workflows/plays/positioning-tournament) | This Motion | ## Wakes None. ## Staffing None. ## Floor None. ## Controls None. ## Builders None. ## Next - [Autonomous agent business](/start/templates/autonomous-agent) - [Agent-run services firm](/start/templates/agent-run-services) - [Managed service firm](/start/templates/managed-service-firm) - [Solo SaaS](/start/templates/solo-saas) - [Autonomous directory](/start/templates/autonomous-directory) - [Founder-led marketplace](/start/templates/founder-marketplace) ## Example A [Startup](/business/nouns/startup) sells a tool that answers security questionnaires for software vendors. Its [Sales Lead](/agents/sales/sales-lead) Agent books demos through LinkedIn outbound. A vendor's head of security signs an annual order, and twelve staff get seats. # b2c URL: /business/motions/b2c · Id: `motion:b2c` > b2c is the Motion where a person buys the Offer for their own use. b2c is the [Motion](/business/nouns/motion) where a person buys the [Offer](/business/nouns/offer) for their own use. The [Site](/business/nouns/site) and [App](/business/nouns/app) lead, and checkout takes one step. ## Adds | Kind | Item | From | | --- | --- | --- | | Buyer | A person, paying for themselves. | This Motion | | Demand Play | [Answer engine optimization](/workflows/plays/aeo) | This Motion | | Demand Play | [Programmatic SEO](/workflows/plays/programmatic-seo) | This Motion | | Demand Play | [Editorial SEO](/workflows/plays/editorial-seo) | This Motion | | Demand Play | [Paid search](/workflows/plays/paid-search) | This Motion | | Demand Play | [Paid social](/workflows/plays/paid-social) | This Motion | | Demand Play | [Retargeting](/workflows/plays/retargeting) | This Motion | | Demand Play | [Organic social](/workflows/plays/organic-social) | This Motion | | Demand Play | [Community answers](/workflows/plays/community-answers) | This Motion | | Demand Play | [Marketplace listings](/workflows/plays/marketplace-listings) | This Motion | | Demand Play | [Directory listings](/workflows/plays/directory-listings) | This Motion | | Demand Play | [Category hubs](/workflows/plays/category-hubs) | This Motion | | Demand Play | [Launch sites](/workflows/plays/launch-sites) | This Motion | | Demand Play | [Customer referrals](/workflows/plays/customer-referrals) | This Motion | | Demand Play | [Commission partners](/workflows/plays/commission-partners) | This Motion | | Demand Play | [Data stories](/workflows/plays/data-stories) | This Motion | | Demand Play | [Owned newsletter](/workflows/plays/owned-newsletter) | This Motion | | Demand Play | [Product-led growth](/workflows/plays/product-led) | This Motion | | Demand Play | [House ads](/workflows/plays/house-ads) | This Motion | | Demand Play | [Portfolio cross-sell](/workflows/plays/cross-sell) | This Motion | | Demand Play | [Engagement bridge](/workflows/plays/engagement-bridge) | This Motion | | Demand Play | [Video ladder](/workflows/plays/video-ladder) | This Motion | | Demand Play | [Promote winners](/workflows/plays/promote-winners) | This Motion | | Demand Play | [Reserve drop](/workflows/plays/reserve-drop) | This Motion | | Demand Play | [Creator probe](/workflows/plays/creator-probe) | This Motion | | Demand Play | [Creator partnership](/workflows/plays/creator-partnership) | This Motion | | Demand Play | [Creator ads](/workflows/plays/creator-ads) | This Motion | | Demand Play | [Free tools](/workflows/plays/free-tools) | This Motion | | Demand Play | [Lead nurture](/workflows/plays/lead-nurture) | This Motion | | Demand Play | [Made with](/workflows/plays/made-with) | This Motion | | Demand Play | [Review requests](/workflows/plays/review-requests) | This Motion | | Demand Play | [Switch kit](/workflows/plays/switch-kit) | This Motion | | Demand Play | [Category kit](/workflows/plays/category-kit) | This Motion | | Demand Play | [Launch week](/workflows/plays/launch-week) | This Motion | | Demand Play | [Positioning tournament](/workflows/plays/positioning-tournament) | This Motion | ## Wakes None. ## Staffing None. ## Floor None. ## Controls None. ## Builders None. ## Next - [Solo SaaS](/start/templates/solo-saas) - [Autonomous directory](/start/templates/autonomous-directory) - [Founder-led marketplace](/start/templates/founder-marketplace) - [Licensed professional network](/start/templates/licensed-network) - [Autonomous storefront](/start/templates/autonomous-storefront) ## Example A [Startup](/business/nouns/startup) sells a $6 a month App that plans the week's meals from what is in the fridge. Short videos on TikTok and Instagram bring people to the Site, and they pay by card in one step. # b2d URL: /business/motions/b2d · Id: `motion:b2d` > b2d is the Motion where a developer buys the Offer to build it into their own Software. b2d is the [Motion](/business/nouns/motion) where a developer buys the [Offer](/business/nouns/offer) to build it into their own [Software](/business/nouns/software). The docs, API, SDK, and CLI lead, and the developer often pays by card before their company signs. ## Adds | Kind | Item | From | | --- | --- | --- | | Buyer | A developer, often on a card before their company signs. | This Motion | | Demand Play | [Answer engine optimization](/workflows/plays/aeo) | This Motion | | Demand Play | [Programmatic SEO](/workflows/plays/programmatic-seo) | This Motion | | Demand Play | [Sponsorships](/workflows/plays/sponsorships) | This Motion | | Demand Play | [Organic social](/workflows/plays/organic-social) | This Motion | | Demand Play | [Community answers](/workflows/plays/community-answers) | This Motion | | Demand Play | [Integration partners](/workflows/plays/integration-partners) | This Motion | | Demand Play | [Agent registries](/workflows/plays/agent-registries) | This Motion | | Demand Play | [Launch sites](/workflows/plays/launch-sites) | This Motion | | Demand Play | [Customer referrals](/workflows/plays/customer-referrals) | This Motion | | Demand Play | [Commission partners](/workflows/plays/commission-partners) | This Motion | | Demand Play | [Data stories](/workflows/plays/data-stories) | This Motion | | Demand Play | [Owned newsletter](/workflows/plays/owned-newsletter) | This Motion | | Demand Play | [Product-led growth](/workflows/plays/product-led) | This Motion | | Demand Play | [Open source](/workflows/plays/open-source) | This Motion | | Demand Play | [Developer relations](/workflows/plays/developer-relations) | This Motion | | Demand Play | [House ads](/workflows/plays/house-ads) | This Motion | | Demand Play | [Portfolio cross-sell](/workflows/plays/cross-sell) | This Motion | | Demand Play | [Engagement bridge](/workflows/plays/engagement-bridge) | This Motion | | Demand Play | [Creator probe](/workflows/plays/creator-probe) | This Motion | | Demand Play | [Creator partnership](/workflows/plays/creator-partnership) | This Motion | | Demand Play | [Free tools](/workflows/plays/free-tools) | This Motion | | Demand Play | [Lead nurture](/workflows/plays/lead-nurture) | This Motion | | Demand Play | [Made with](/workflows/plays/made-with) | This Motion | | Demand Play | [Review requests](/workflows/plays/review-requests) | This Motion | | Demand Play | [Switch kit](/workflows/plays/switch-kit) | This Motion | | Demand Play | [Category kit](/workflows/plays/category-kit) | This Motion | | Demand Play | [Founder voice](/workflows/plays/founder-voice) | This Motion | | Demand Play | [Launch week](/workflows/plays/launch-week) | This Motion | | Demand Play | [Positioning tournament](/workflows/plays/positioning-tournament) | This Motion | ## Wakes None. ## Staffing None. ## Floor None. ## Controls None. ## Builders None. ## Next - [Autonomous data API](/start/templates/autonomous-data-api) ## Example A [Startup](/business/nouns/startup) sells address validation. A developer finds it on npm, gets a key with no sales call, and pays per call. Six months later, the developer's employer signs an annual contract. # b2h2a URL: /business/motions/b2h2a · Id: `motion:b2h2a` > b2h2a is the Motion where a person buys the Offer and their Agent uses it. b2h2a is the [Motion](/business/nouns/motion) where a person buys the [Offer](/business/nouns/offer) and their [Agent](/business/nouns/agent) uses it. The person subscribes once, and the Agent works through the MCP server. ## Adds | Kind | Item | From | | --- | --- | --- | | Buyer | A person, buying for the Agent that works for them. | This Motion | | Demand Play | [Answer engine optimization](/workflows/plays/aeo) | This Motion | | Demand Play | [Made with](/workflows/plays/made-with) | This Motion | ## Wakes None. ## Staffing None. ## Floor None. ## Controls None. ## Builders None. ## Next - [Autonomous agent business](/start/templates/autonomous-agent) ## Example A person pays $9 a month for a fare tracker. Their assistant Agent connects over MCP, watches fares for the trips on their calendar, and alerts them when a fare drops below their [Limit](/business/nouns/limit). # Motions URL: /business/motions · Id: `page:business/motions` > A Motion names who buys an Offer and who acts with it, and it reshapes the template and the demand Plays that fit. A [Motion](/business/nouns/motion) names who buys an [Offer](/business/nouns/offer) and who acts with it, written as a chain such as b2b or b2a2c. It is a property of the Offer, and it reshapes the template around it. ## Reading the chain The first `b` is the [Startup](/business/nouns/startup), and each later letter is a party the Offer passes through. The letters are: - `b`: a business. - `c`: a person buying for themselves. - `d`: a developer. - `h`: a person who hands the Offer on. - `a`: an [Agent](/business/nouns/agent). So b2a2c reads: a Startup sells to an Agent, which buys for a person. In b2h2a, a person buys and their Agent uses what they bought. ## What a Motion changes - Who the [Customer](/business/nouns/customer) is: the business, the person, the developer, or the principal an Agent acts for. - Who [Actions](/business/nouns/action) are by and for: in b2a2b, Actions are by the buying Agent and for its business. - When a [Mandate](/business/nouns/mandate) or an [Approval](/business/nouns/approval) applies: an Agent pays within its Mandate, and a purchase over its [Limit](/business/nouns/limit) waits for its principal. - Which [Interfaces](/business/nouns/interface) lead: b2d leads with the API, SDK, and CLI, b2a with the MCP server, and b2c with the [Site](/business/nouns/site) and [App](/business/nouns/app). One [Product](/business/nouns/product) can sell through several Motions. A meeting-notes Product sells b2c through its App, and b2h2a through its MCP server to the assistants people already use. ## Motion selects demand Plays Each Motion fits the demand [Plays](/business/nouns/play) that reach its buyer where that buyer looks: - b2c: [Paid social](/workflows/plays/paid-social) on Instagram, TikTok, and Facebook. - b2b: [LinkedIn outbound](/workflows/plays/linkedin-outbound), [Cold email](/workflows/plays/cold-email), and [Paid search](/workflows/plays/paid-search) on Google Search. - b2d: [Developer relations](/workflows/plays/developer-relations) and [Open source](/workflows/plays/open-source), with packages on npm and code on GitHub. - b2a: [Answer engine optimization](/workflows/plays/aeo), [Agent registries](/workflows/plays/agent-registries) such as the MCP Registry, and [Agent-to-agent selling](/workflows/plays/agent-to-agent). Every Motion page lists the full set, generated from each Play's fit. ## The catalog | Motion | Buyer | Leads with | | --- | --- | --- | | [b2b](/business/motions/b2b) | A business, through the person who signs for it. | `api`, `sdk`, `webhooks` | | [b2c](/business/motions/b2c) | A person, paying for themselves. | None. | | [b2d](/business/motions/b2d) | A developer, often on a card before their company signs. | `api`, `sdk`, `cli` | | [b2a](/business/motions/b2a) | An Agent, acting under its own Mandate. | `mcp`, `api` | | [b2h2a](/business/motions/b2h2a) | A person, buying for the Agent that works for them. | `mcp` | | [b2a2b](/business/motions/b2a2b) | A business, through an Agent holding its Mandate. | `mcp`, `api` | | [b2a2c](/business/motions/b2a2c) | A person, through an Agent holding their Mandate. | `mcp`, `api` | | [b2a2d](/business/motions/b2a2d) | A developer, through the coding Agent that builds for them. | `mcp`, `api`, `sdk` | # Names and ids URL: /business/names-and-ids · Id: `page:business/names-and-ids` > How every record, Noun, Verb, Event and property is named, so one name works in the API, SDK, CLI and MCP server and in every sentence. Every record has one id, its URL, and every part of the model has one name. A founder's agent and a developer's code use the same names, so a name read on any page works in any call. ## A record's id is its URL ```json { "$id": "https://api.sb/leaseline.app/orders/order_1", "$type": "Order", "$version": 4, "status": "paid" } ``` `$id` is the record's address: `https://api.sb/`, the [Startup](/business/nouns/startup)'s namespace, the plural path and the record. The namespace is the Startup's [Domain](/business/nouns/domain), so every record says which business owns it. `$type` names the [Noun](/business/nouns/noun), and `$version` counts the record's writes. A field that starts with `$` is metadata. Every other field is a property listed on the Noun's page. ## One name per part | Part | Written | Example | | --- | --- | --- | | Noun | PascalCase, singular | `CreditGrant` | | Path segment | kebab-case, plural | `/credit-grants` | | Record key in a payload | camelCase | `creditGrant` | | Property and value | camelCase | `status: pastDue` | | [Verb](/business/nouns/verb) | camelCase action form | `requestSetup` | | Verb id | Noun, a dot, the Verb | `Tenant.requestSetup` | | [Event](/business/nouns/event) | Noun, a dot, the past tense | `Tenant.setupRequested` | A Verb id is the same string on every [Interface](/business/nouns/interface). It is the API's operation id, the SDK method `$.Tenant.requestSetup`, the CLI's `do Tenant.requestSetup` and the MCP server's call. An agent that learns one form knows all four. ## Names in sentences These docs write a Noun as a capitalized word, so "an [Offer](/business/nouns/offer)" means the record type and nothing looser. Each Noun has words it never goes by, and no page uses them. The page on [colliding terms](/business/terms) names the words other tools use differently. Stripe's own fields keep Stripe's snake_case, such as `unit_amount`, and appear only where a page maps a record to Stripe. Every call here takes camelCase. ## Names you add A Noun or Verb the Startup adds follows the same rules, and its Verb ids work on all four Interfaces. A `Lease.mdx` file with a `renew` Verb serves `/leases`, the Verb id `Lease.renew` and the Event `Lease.renewed`. [Nouns](/code/file-conventions/nouns) shows the file. # Nouns & Verbs URL: /business/nouns-and-verbs · Id: `page:business/nouns-and-verbs` > A Noun is a type of record a business keeps, and a Verb is what can be done to one, so together they define every Startup. A [Customer](/business/nouns/customer) and an [Offer](/business/nouns/offer) are [Nouns](/business/nouns/noun); publishing an Offer is a [Verb](/business/nouns/verb), named `Offer.publish`. Every Verb emits an [Event](/business/nouns/event) in the past tense: `Offer.publish` emits `Offer.published`. ## How they connect Every [Relationship](/business/nouns/relationship) reads from both ends, and [Relationships](/business/relationships) lists all of them. ## Every Noun and its Verbs # Access Level URL: /business/nouns/access-level · Id: `noun:access-level` > An Access Level is a named preset of Permissions a Worker holds in a namespace, such as owner or viewer; it is never a Role. An Access Level is a named preset of [Permissions](/business/nouns/permission) a [Worker](/business/nouns/worker) holds in a namespace, such as owner or viewer; it is never a [Role](/business/nouns/role). ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `name` | `string` | Yes | Its name, such as `owner`, `admin`, `member`, or `viewer`. | | `grants` | list of [Permission](/business/nouns/permission) | Yes | The Permissions it presets: read, write or all Verbs, or named Verbs, on Nouns. | | `order` | `integer` | No | Its rank: 1 holds the most access. | ## Object ```json { "$id": "https://api.sb/patentpad.com/access-levels/access_level_1", "$type": "AccessLevel", "name": "owner", "grants": [ "permission_1" ], "order": 1 } ``` ## Relationships - An Access Level **has** many [Workers](/business/nouns/worker): a [Worker](/business/nouns/worker) holds one Access Level in each namespace it works in, apart from the [Role](/business/nouns/role) it fills. `workers`, inverse [`hasAccess`](/business/nouns/worker#rel-has-access). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [AccessLevel.get](/business/nouns/access-level/get) | Returns one Access Level by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [AccessLevel.list](/business/nouns/access-level/list) | Returns Access Levels, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | An Access Level is kept forever and never edited: it has no `update` or `delete`. ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `AccessLevel.get` | Yes | Yes | Yes | Yes | | `AccessLevel.list` | Yes | Yes | Yes | Yes | ## Call it **Ask** ```text Show me the latest access level. ``` **API** ```bash curl https://api.sb/kilnbakery.com/access-levels/access_level_1 \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/kilnbakery.com", "$type": "AccessLevel", "$id": "https://api.sb/kilnbakery.com/access-levels/access_level_1", "accessLevel": { "$id": "https://api.sb/kilnbakery.com/access-levels/access_level_1", "$type": "AccessLevel", "name": "owner", "grants": [ "permission_1" ] }, "links": { "self": "https://api.sb/kilnbakery.com/access-levels/access_level_1", "up": "https://api.sb/kilnbakery.com/access-levels" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const accessLevel = await $.AccessLevel.get({ id: 'access_level_1' }) ``` **CLI** ```bash npx startup-builder do AccessLevel.get --json '{"id":"access_level_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.AccessLevel.get({ id: 'access_level_1' })" } } ``` ## Example A design contractor joins a [Startup](/business/nouns/startup) as a `member`. They can edit [Offers](/business/nouns/offer) and [Pages](/business/nouns/page), but not a [Permission](/business/nouns/permission) or a [Limit](/business/nouns/limit). The same person fills the [Designer](/agents/product/designer) Role: the Access Level sets what they may touch, and the Role sets the work they own. # Account URL: /business/nouns/account · Id: `noun:account` > An Account is a ledger account in a Startup’s chart of accounts; a cash Account is held at one place, such as Treasury. An Account is a ledger account in a [Startup](/business/nouns/startup)’s chart of accounts; a cash Account is held at one place, such as Treasury. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `class` | `string` | Yes | One of `cash`, `asset`, `receivable`, `liability`, `equity`, `revenue`, or `expense`. | | `heldAt` | `string` | No | One of `payments`, `cards`, `treasury`, `bank`, or `company` (a share of the holding Company’s cash): where a cash Account is held. | | `balance` | `money` | No | Computed on read from Entries; never stored. | | `pending` | `money` | No | Computed: money on its way in that has not settled yet. | | `payoutSchedule` | `string` | No | One of `daily`, `weekly`, `monthly`, or `manual`: when the payments balance pays out. | ## Object ```json { "$id": "https://api.sb/routewise.dev/accounts/account_1", "$type": "Account", "class": "cash", "heldAt": "payments", "balance": { "amount": 25, "currency": "USD" }, "pending": { "amount": 25, "currency": "USD" }, "payoutSchedule": "daily" } ``` ## Relationships - An Account **has** many [Entries](/business/nouns/entry): each [Entry](/business/nouns/entry) posts to one Account, and an Account’s balance is the sum of its Entries. `entries`, inverse [`postsTo`](/business/nouns/entry#rel-posts-to). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Account.payout](/business/nouns/account/payout) | Payout sends available cash from the payments balance to the owner’s bank and lists every Transaction the payout carries. | [Treasurer](/agents/finance/treasurer) | [`Account.paidOut`](/business/events/Account.paidOut) | One-way (money): `send`, `do` | | [Account.sweep](/business/nouns/account/sweep) | Sweep moves cash between two cash Accounts of the same owner, once or on a standing rule, within the Treasurer’s Limit. | [Treasurer](/agents/finance/treasurer) | [`Account.swept`](/business/events/Account.swept) | Two-way: `try`, `send`, `do` | | [Account.get](/business/nouns/account/get) | Returns one Account by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Account.list](/business/nouns/account/list) | Returns Accounts, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | An Account is kept forever and never edited: it has no `update` or `delete`. ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Account.get` | Yes | Yes | Yes | Yes | | `Account.list` | Yes | Yes | Yes | Yes | | `Account.payout` | Yes | No | No | No | | `Account.sweep` | Yes | Yes | Yes | No | ## Stripe **Treasury FinancialAccount** (`treasury.financial_account`), for an Account whose `heldAt` is `treasury`. The source of truth is Stripe: db.sb mirrors it, written only from Stripe’s webhooks. | Property | Stripe field | Source of truth | | --- | --- | --- | | `balance` | `balance.cash` | Stripe | | `pending` | `balance.inbound_pending` | Stripe | ## Call it **Ask** ```text Sweep my account. ``` **API** ```bash curl -X POST https://api.sb/ledgerlark.com/accounts/account_1/sweep \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"to":"account_1"}' ``` ```json { "api": "https://api.sb/ledgerlark.com", "account": { "$id": "https://api.sb/ledgerlark.com/accounts/account_1", "$type": "Account", "class": "cash" }, "transaction": { "$id": "https://api.sb/ledgerlark.com/transactions/transaction_1", "$type": "Transaction", "kind": "charge", "amount": { "amount": 400, "currency": "USD" } }, "action": { "$id": "https://api.sb/ledgerlark.com/actions/action_1", "operation": "Account.sweep", "status": "done" }, "links": { "self": "https://api.sb/ledgerlark.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { account, transaction } = await $.Account.sweep({ from: 'account_1', to: 'account_1' }) ``` **CLI** ```bash npx startup-builder do Account.sweep --json '{"from":"account_1","to":"account_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Account.sweep({ from: 'account_1', to: 'account_1' })" } } ``` ## Example A tutoring Startup keeps $3,000 of reserve cash in an Account of class `cash` held at `treasury`. Its balance is the sum of the [Entries](/business/nouns/entry) posted to it, and each week the [Treasurer](/agents/finance/treasurer) checks it against the figure Stripe reports. # payout URL: /business/nouns/account/payout · Id: `verb:Account.payout` · Call: `await $.Account.payout({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Payout sends available cash from the payments balance to the owner’s bank and lists every Transaction the payout carries. Payout sends available cash from the payments balance to the owner’s bank and lists every [Transaction](/business/nouns/transaction) the payout carries. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `account` | [Account](/business/nouns/account) | Yes | The payments balance: the cash Account held at `payments`. | | `amount` | `money` | No | How much to send. Defaults to everything available. | | `instant` | `boolean` | No | True to send it within minutes to an eligible debit card or bank, for Stripe’s instant payout cost. | | `schedule` | `string` | No | Sets the Account’s `payoutSchedule` from now on, in place of sending a payout now. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `account` | [Account](/business/nouns/account) | Yes | The payments balance after the payout. | | `transaction` | [Transaction](/business/nouns/transaction) | Yes | The payout, a Transaction of kind `payout`. | ## Effects - Emits [`Account.paidOut`](/business/events/Account.paidOut). - Performed by the [Treasurer](/agents/finance/treasurer). - One-way (money): it waits out its delay window, and runs in the `send` and `do` modes. - Runs on the Account’s `payoutSchedule`, daily by default; a call sends one now, or with `schedule` changes the rhythm. - A payout the bank returns lands back in the payments balance and opens a Task to fix the bank details. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Account.payout](/business/nouns/account/payout) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Medium: one-way, bounded (money) | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | 1 business hour, in which a watcher can pause, redirect or cancel it; then it runs. | | Limit | The spend [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) or [Mandate](/business/nouns/mandate) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Pay out the balance of my account to the bank. ``` **API** ```bash curl -X POST https://api.sb/routewise.dev/accounts/account_1/payout \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/routewise.dev", "account": { "$id": "https://api.sb/routewise.dev/accounts/account_1", "$type": "Account", "class": "cash" }, "transaction": { "$id": "https://api.sb/routewise.dev/transactions/transaction_1", "$type": "Transaction", "kind": "charge", "amount": { "amount": 25, "currency": "USD" } }, "action": { "$id": "https://api.sb/routewise.dev/actions/action_1", "operation": "Account.payout", "status": "done" }, "links": { "self": "https://api.sb/routewise.dev/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { account, transaction } = await $.Account.payout({ account: 'account_1' }) ``` **CLI** ```bash npx startup-builder do Account.payout --json '{"account":"account_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Account.payout({ account: 'account_1' })" } } ``` Guides that call it: [Pay out to my bank](/systems/finance/pay-out-to-my-bank). # sweep URL: /business/nouns/account/sweep · Id: `verb:Account.sweep` · Call: `await $.Account.sweep({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Sweep moves cash between two cash Accounts of the same owner, once or on a standing rule, within the Treasurer’s Limit. Sweep moves cash between two cash [Accounts](/business/nouns/account) of the same owner, once or on a standing rule, within the [Treasurer](/agents/finance/treasurer)’s [Limit](/business/nouns/limit). ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `from` | [Account](/business/nouns/account) | Yes | The cash Account the money leaves. | | `to` | [Account](/business/nouns/account) | Yes | The cash Account it lands in. | | `amount` | `money` | No | How much to move. Leave it out and set `keep` to move everything above a floor. | | `keep` | `money` | No | Leave this much in `from` and move the rest. | | `repeat` | `string` | No | Turns the move into a standing rule that sweeps on this schedule. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `account` | [Account](/business/nouns/account) | Yes | The `to` Account, with the money landed. | | `transaction` | [Transaction](/business/nouns/transaction) | Yes | The move, reconciled on both Accounts. | ## Effects - Emits [`Account.swept`](/business/events/Account.swept). - Performed by the [Treasurer](/agents/finance/treasurer). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - From the payments balance to the card balance, the money lands at once; from a bank it takes up to five business days. - A standing rule skips a day when the move would leave `from` below `keep`. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Account.sweep](/business/nouns/account/sweep) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Sweep my account. ``` **API** ```bash curl -X POST https://api.sb/ledgerlark.com/accounts/account_1/sweep \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"to":"account_1"}' ``` ```json { "api": "https://api.sb/ledgerlark.com", "account": { "$id": "https://api.sb/ledgerlark.com/accounts/account_1", "$type": "Account", "class": "cash" }, "transaction": { "$id": "https://api.sb/ledgerlark.com/transactions/transaction_1", "$type": "Transaction", "kind": "charge", "amount": { "amount": 400, "currency": "USD" } }, "action": { "$id": "https://api.sb/ledgerlark.com/actions/action_1", "operation": "Account.sweep", "status": "done" }, "links": { "self": "https://api.sb/ledgerlark.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { account, transaction } = await $.Account.sweep({ from: 'account_1', to: 'account_1' }) ``` **CLI** ```bash npx startup-builder do Account.sweep --json '{"from":"account_1","to":"account_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Account.sweep({ from: 'account_1', to: 'account_1' })" } } ``` Guides that call it: [Move money between accounts](/systems/finance/move-money). # Acquisition URL: /business/nouns/acquisition · Id: `noun:acquisition` > An Acquisition is how a Visitor or Prospect first arrived, recorded on its first Event: the referrer kind, the Play, the campaign, and the medium. An Acquisition is how a [Visitor](/business/nouns/visitor) or [Prospect](/business/nouns/prospect) first arrived, recorded on its first [Event](/business/nouns/event): the referrer kind, the [Play](/business/nouns/play), the campaign, and the medium. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `kind` | `string` | Yes | The referrer kind: one of `search`, `answer`, `agent`, `referral`, `ad`, `outbound`, or `direct`. | | `play` | [Play](/business/nouns/play) | No | The Play that produced the first touch, when one did. | | `venue` | `string` | No | The venue id where the touch happened, such as a search engine, an answer engine, or a Mailbox. | | `campaign` | [Campaign](/business/nouns/campaign) | No | The Campaign behind a paid placement or a scheduled send. | | `ad` | [Ad](/business/nouns/ad) | No | The Ad clicked, for a paid or house placement. | | `page` | [Page](/business/nouns/page) | No | The first Page the Visitor saw. | | `keyword` | [Keyword](/business/nouns/keyword) | No | The Keyword or prompt, when the venue reports it. | | `angle` | `string` | No | The angle the first touch carried: the message the Play ran. | | `referrer` | `string` | No | The linking host, as the request reported it. | | `partner` | [Partner](/business/nouns/partner) | No | The Partner or creator credited, for referral, creator and commission Plays. | | `reported` | `text` | No | What the person answered when asked how they heard, kept word for word. | | `at` | `datetime` | Yes | When the first Event arrived. | ## Object ```json { "$id": "https://api.sb/routewise.dev/acquisitions/acquisition_1", "$type": "Acquisition", "kind": "search", "play": "play_1", "venue": "google-search", "campaign": "campaign_1", "ad": "ad_1", "page": "page_1", "keyword": "keyword_1", "angle": "Example angle", "referrer": "news.ycombinator.com", "partner": "partner_1", "reported": "Example reported", "at": "2026-10-22T12:00:00Z" } ``` ## Relationships - An Acquisition **has** many [Customers](/business/nouns/customer): a [Customer](/business/nouns/customer) inherits the Acquisition of the [Lead](/business/nouns/lead) it was; [Metrics](/business/nouns/metric) and payouts read this one row. `customers`, inverse [`acquiredBy`](/business/nouns/customer#rel-acquired-by). - An Acquisition **has** many [Leads](/business/nouns/lead): each [Lead](/business/nouns/lead) keeps the Acquisition that first brought it, through either door: a [Visit](/business/nouns/visit) or an outbound reply. `leads`, inverse [`acquiredBy`](/business/nouns/lead#rel-acquired-by). - An Acquisition **has** many [Prospects](/business/nouns/prospect): a [Prospect](/business/nouns/prospect)’s Acquisition names the outbound [Play](/business/nouns/play) and [Mailbox](/business/nouns/mailbox) that first reached it. `prospects`, inverse [`acquiredBy`](/business/nouns/prospect#rel-acquired-by). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Acquisition.get](/business/nouns/acquisition/get) | Returns one Acquisition by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Acquisition.list](/business/nouns/acquisition/list) | Returns Acquisitions, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | An Acquisition is kept forever and never edited: it has no `update` or `delete`. ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Acquisition.get` | Yes | Yes | Yes | Yes | | `Acquisition.list` | Yes | Yes | Yes | Yes | ## Call it **Ask** ```text Show me the latest acquisition. ``` **API** ```bash curl https://api.sb/ledgerlark.com/acquisitions/acquisition_1 \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/ledgerlark.com", "$type": "Acquisition", "$id": "https://api.sb/ledgerlark.com/acquisitions/acquisition_1", "acquisition": { "$id": "https://api.sb/ledgerlark.com/acquisitions/acquisition_1", "$type": "Acquisition", "kind": "search", "at": "2026-10-22T12:00:00Z" }, "links": { "self": "https://api.sb/ledgerlark.com/acquisitions/acquisition_1", "up": "https://api.sb/ledgerlark.com/acquisitions" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const acquisition = await $.Acquisition.get({ id: 'acquisition_1' }) ``` **CLI** ```bash npx startup-builder do Acquisition.get --json '{"id":"acquisition_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Acquisition.get({ id: 'acquisition_1' })" } } ``` ## Example A clinic manager asks [ChatGPT](/workflows/plays#chatgpt) for shift-scheduling software and opens the pricing [Page](/business/nouns/page) it cites. Her first Event writes an Acquisition with `kind: answer`, `venue: chatgpt` and the [answer engine optimization](/workflows/plays/aeo) Play. When she subscribes, her [Customer](/business/nouns/customer) record keeps it, and that Play’s ledger counts her revenue. # answer URL: /business/nouns/action/answer · Id: `verb:Action.answer` · Call: `await $.Action.answer({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Answer gives the reply to an Action’s open Question, through any Interface, and the Action resumes. Answer replies to an open [Question](/business/nouns/question) on an [Action](/business/nouns/action), from the asked [Party](/business/nouns/party) or an [Agent](/business/nouns/agent) under its [Mandate](/business/nouns/mandate), and resumes the Action. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `action` | [Action](/business/nouns/action) | Yes | The Action waiting on the Question. | | `question` | [Question](/business/nouns/question) | Yes | The Question answered. | | `payload` | `json` | Yes | The answer, matching the Question’s choices or schema. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `action` | [Action](/business/nouns/action) | Yes | The resumed Action. | ## Effects - Emits [`Action.answered`](/business/events/Action.answered). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Records who answered and through which Interface; an agent answering for a Human records both, under a Mandate. - A free-text reply in the record’s Thread becomes an answer once an agent maps it to the schema. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Action.answer](/business/nouns/action/answer) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Answer the latest action with a question. ``` **API** ```bash curl -X POST https://api.sb/petpantry.shop/actions/action_1/answer \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"question":"question_1","payload":{}}' ``` ```json { "api": "https://api.sb/petpantry.shop", "action": { "$id": "https://api.sb/petpantry.shop/actions/action_1", "$type": "Action", "status": "done", "mode": "try", "operation": "Action.answer" }, "links": { "self": "https://api.sb/petpantry.shop/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const action = await $.Action.answer({ action: 'action_1', question: 'question_1', payload: {} }) ``` **CLI** ```bash npx startup-builder do Action.answer --json '{"action":"action_1","question":"question_1","payload":{}}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Action.answer({ action: 'action_1', question: 'question_1', payload: {} })" } } ``` # ask URL: /business/nouns/action/ask · Id: `verb:Action.ask` · Call: `await $.Action.ask({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Ask puts a Question to a Party, a Role, or a Worker and holds the Action `pending` with reason `awaitingInput`. Ask puts a [Question](/business/nouns/question) to a [Party](/business/nouns/party) during an [Action](/business/nouns/action) and holds it `pending` with reason `awaitingInput` until it is answered. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `action` | [Action](/business/nouns/action) | Yes | The Action that needs an answer to go on. | | `to` | [Thing](/business/nouns/thing) | Yes | Who is asked: a Party, a Role, or a Worker. | | `text` | `text` | Yes | The question, in one message. | | `choices` | `string[]` | No | The answers offered. | | `schema` | `json` | No | The typed answer’s shape. | | `answerBy` | `datetime` | No | When the Action’s timeout rule applies. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `question` | [Question](/business/nouns/question) | Yes | The Question, posted in the record’s Thread. | | `action` | [Action](/business/nouns/action) | Yes | The Action, now pending with reason `awaitingInput`. | ## Effects - Emits [`Action.asked`](/business/events/Action.asked). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Pauses an Order’s delivery window and service level while the Customer is the one asked. - Renders as a Portal form, an email, a chat card, or an MCP elicitation, by where the asked party is. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Action.ask](/business/nouns/action/ask) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Ask the latest action with a thing. ``` **API** ```bash curl -X POST https://api.sb/routewise.dev/actions/action_1/ask \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"to":"thing_1","text":"Example text"}' ``` ```json { "api": "https://api.sb/routewise.dev", "question": { "$id": "https://api.sb/routewise.dev/questions/question_1", "$type": "Question", "to": "thing_1", "text": "Example text" }, "action": { "$id": "https://api.sb/routewise.dev/actions/action_1", "$type": "Action", "status": "done", "mode": "try", "operation": "Action.ask" }, "links": { "self": "https://api.sb/routewise.dev/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { question, action } = await $.Action.ask({ action: 'action_1', to: 'thing_1', text: 'Example text' }) ``` **CLI** ```bash npx startup-builder do Action.ask --json '{"action":"action_1","to":"thing_1","text":"Example text"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Action.ask({ action: 'action_1', to: 'thing_1', text: 'Example text' })" } } ``` # attest URL: /business/nouns/action/attest · Id: `verb:Action.attest` · Call: `await $.Action.attest({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Attest records a credentialed Human’s signed performance of a Reserved Act that an Action needs to finish. Attest records a credentialed [Human](/business/nouns/human)’s signed performance of a [Reserved Act](/business/nouns/reserved-act) that an [Action](/business/nouns/action) needs to finish. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `action` | [Action](/business/nouns/action) | Yes | The Action that waits on the Reserved Act. | | `credential` | [Credential](/business/nouns/credential) | Yes | The Credential that authorizes it. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `action` | [Action](/business/nouns/action) | Yes | The Action, free to finish. | ## Effects - Emits [`Action.attested`](/business/events/Action.attested). - Performed by the [Legal Lead](/agents/legal/legal-lead). - Records who signed, under which Credential, and when. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The input does not match the schema of the operation. | [`invalid-input`](/code/api/errors/invalid-input) | Read the schema of the operation, then send every required field with the right type. | [Action.attest](/business/nouns/action/attest) | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Action.attest](/business/nouns/action/attest) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Attest the latest action with a credential. ``` **API** ```bash curl -X POST https://api.sb/shiftnote.app/actions/action_1/attest \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"credential":"credential_1"}' ``` ```json { "api": "https://api.sb/shiftnote.app", "action": { "$id": "https://api.sb/shiftnote.app/actions/action_1", "$type": "Action", "status": "done", "mode": "try", "operation": "Action.attest" }, "links": { "self": "https://api.sb/shiftnote.app/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const action = await $.Action.attest({ action: 'action_1', credential: 'credential_1' }) ``` **CLI** ```bash npx startup-builder do Action.attest --json '{"action":"action_1","credential":"credential_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Action.attest({ action: 'action_1', credential: 'credential_1' })" } } ``` # cancel URL: /business/nouns/action/cancel · Id: `verb:Action.cancel` · Call: `await $.Action.cancel({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Cancel stops a pending Action, sets its status to `canceled`, and runs its compensation. Cancel stops a pending [Action](/business/nouns/action), sets its status to `canceled`, and runs its compensation. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `action` | [Action](/business/nouns/action) | Yes | The pending Action. | | `reason` | `text` | No | Why it stops. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `action` | [Action](/business/nouns/action) | Yes | The canceled Action. | ## Effects - Emits [`Action.canceled`](/business/events/Action.canceled). - Performed by the [Risk Analyst](/agents/operations/risk-analyst). - Moves the Noun it acted on to its canceled state, when the Noun has one. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Action.cancel](/business/nouns/action/cancel) | | The record is not in a state that allows this Verb, so the call is refused. | [`refused`](/code/api/errors/refused) | Read the record, run the Verb that moves it to an allowed state, then retry. | [Action.cancel](/business/nouns/action/cancel) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Cancel the latest action. ``` **API** ```bash curl -X POST https://api.sb/petpantry.shop/actions/action_1/cancel \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/petpantry.shop", "action": { "$id": "https://api.sb/petpantry.shop/actions/action_1", "$type": "Action", "status": "done", "mode": "try", "operation": "Action.cancel" }, "links": { "self": "https://api.sb/petpantry.shop/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const action = await $.Action.cancel({ action: 'action_1' }) ``` **CLI** ```bash npx startup-builder do Action.cancel --json '{"action":"action_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Action.cancel({ action: 'action_1' })" } } ``` # evaluate URL: /business/nouns/action/evaluate · Id: `verb:Action.evaluate` · Call: `await $.Action.evaluate({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Evaluate grades an Action’s output against a rubric and records the verdict as an Event. Evaluate grades an [Action](/business/nouns/action)’s output against a rubric and records the verdict as an [Event](/business/nouns/event). ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `action` | [Action](/business/nouns/action) | Yes | The Action whose output is graded. | | `evaluator` | `string` | Yes | The Evaluator to run. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `verdict` | `json` | Yes | The score and the reasons for it. | | `action` | [Action](/business/nouns/action) | Yes | The Action graded, with the verdict attached. | ## Effects - Emits [`Action.evaluated`](/business/events/Action.evaluated). - Performed by the [Quality Lead](/agents/quality/quality-lead). ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The input does not match the schema of the operation. | [`invalid-input`](/code/api/errors/invalid-input) | Read the schema of the operation, then send every required field with the right type. | [Action.evaluate](/business/nouns/action/evaluate) | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Action.evaluate](/business/nouns/action/evaluate) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Evaluate the latest action. ``` **API** ```bash curl -X POST https://api.sb/routewise.dev/actions/action_1/evaluate \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"evaluator":"Example evaluator"}' ``` ```json { "api": "https://api.sb/routewise.dev", "verdict": {}, "action": { "$id": "https://api.sb/routewise.dev/actions/action_1", "$type": "Action", "status": "done", "mode": "try", "operation": "Action.evaluate" }, "links": { "self": "https://api.sb/routewise.dev/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { verdict, action } = await $.Action.evaluate({ action: 'action_1', evaluator: 'Example evaluator' }) ``` **CLI** ```bash npx startup-builder do Action.evaluate --json '{"action":"action_1","evaluator":"Example evaluator"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Action.evaluate({ action: 'action_1', evaluator: 'Example evaluator' })" } } ``` # Action URL: /business/nouns/action · Id: `noun:action` > An Action is one Verb performed by a Worker on a Thing, recorded with its status and every Event it emits. An Action is one [Verb](/business/nouns/verb) performed by a [Worker](/business/nouns/worker) on a [Thing](/business/nouns/thing), recorded with its status and every [Event](/business/nouns/event) it emits. Its [Approvals](/business/nouns/approval) and [Costs](/business/nouns/cost) attach to it, so one record shows who did what, and why. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `status` | `string` | Yes | One of `pending`, `done`, `failed`, `canceled`, or `refused`. | | `reason` | `string` | No | Why a pending Action waits: `queued`, `running`, `retrying`, `awaitingWorker`, `awaitingInput`, `awaitingSource`, `awaitingAction`, or `awaitingTime`. | | `mode` | `string` | Yes | How the caller invoked it: `try`, `send`, or `do`. | | `by` | [Worker](/business/nouns/worker) | No | The Worker that performed it. | | `for` | [Party](/business/nouns/party) | No | The Party it was done on behalf of. | | `via` | `string` | No | The Interface or request it arrived through. | | `on` | `string` | No | The Action or Event that caused it, such as the failed attempt a retry follows. | | `thing` | `string` | No | The record, at the Version the Action was decided against. | | `input` | `json` | No | The input it was called with. | | `createdAt` | `datetime` | No | When it was called. | | `reserved` | `money` | No | The most this Action may cost, held against its Limits from the check until it settles, billed misses included. | ## Object ```json { "$id": "https://api.sb/quietcopy.com/actions/action_1", "$type": "Action", "status": "pending", "reason": "queued", "mode": "try", "by": "worker_1", "for": "party_1", "via": "API", "on": "Invoice.overdue", "thing": "invoice_1@v3", "input": {}, "createdAt": "2026-10-22T12:00:00Z", "reserved": { "amount": 39, "currency": "USD" } } ``` ## Relationships - An Action **acts on** one [Thing](/business/nouns/thing): the [Thing](/business/nouns/thing) an Action changes; a Thing’s history is the Actions that acted on it. `actsOn`, inverse [`actedOnBy`](/business/nouns/thing#rel-acted-on-by). - An Action **has** many [Approvals](/business/nouns/approval): an [Approval](/business/nouns/approval) holds one pending Action that exceeds a [Limit](/business/nouns/limit) or [Mandate](/business/nouns/mandate) until someone allows or refuses it. `approvals`, inverse [`gates`](/business/nouns/approval#rel-gates). - An Action **asks** many [Questions](/business/nouns/question): a pending Action asks [Questions](/business/nouns/question) and waits `awaitingInput` until each is answered or its deadline passes. `asks`, inverse [`action`](/business/nouns/question#rel-action). - An Action **emits** many [Events](/business/nouns/event): a completed Action emits its [Events](/business/nouns/event), which [Triggers](/business/nouns/trigger), [Watches](/business/nouns/watch) and [Metrics](/business/nouns/metric) read. `emits`, inverse [`emittedBy`](/business/nouns/event#rel-emitted-by). - An Action **is executed by** one [Workflow](/business/nouns/workflow): a [Workflow](/business/nouns/workflow) is the durable body of one Action: its steps, retries and waits. `executedBy`, inverse [`executes`](/business/nouns/workflow#rel-executes). - An Action **invokes** one [Verb](/business/nouns/verb): each Action performs one [Verb](/business/nouns/verb), which fixes its inputs, the [Event](/business/nouns/event) it emits and its delay window. `invokes`, inverse [`invokedAs`](/business/nouns/verb#rel-invoked-as). - An Action **posts** many [Costs](/business/nouns/cost): every [Cost](/business/nouns/cost) an Action causes posts to the [Startup](/business/nouns/startup) it ran in, so each Startup’s P&L is complete. `posts`, inverse [`postedBy`](/business/nouns/cost#rel-posted-by). - An Action **runs in** one [Mode](/business/nouns/mode): the [Mode](/business/nouns/mode) the caller chose: `try` stores nothing, `send` returns a pending Action, `do` waits for the result. `runsIn`, inverse [`modeOf`](/business/nouns/mode#rel-mode-of). ## Lifecycle | State | Meaning | Moves to | | --- | --- | --- | | `pending` (first) | Accepted and not finished; its `reason` names who holds the ball. | `done` on [`Action.done`](/business/nouns/action#actiondone); `failed` on [`Action.failed`](/business/nouns/action#actionfailed); `canceled` by [Action.cancel](/business/nouns/action/cancel); `refused` on [`Approval.refused`](/business/events/Approval.refused) when the Approval holds this Action | | `done` | It finished and its effects are written. | None: it ends here. | | `failed` | It stopped with an error; a retry is a new Action linked to this one. | None: it ends here. | | `canceled` | It was stopped before it finished, and its compensation ran. | None: it ends here. | | `refused` | A Guard, a Limit or an Approval refused it, with the reason. | None: it ends here. | ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Action.answer](/business/nouns/action/answer) | Answer gives the reply to an Action’s open Question, through any Interface, and the Action resumes. | [Party](/business/nouns/party) | [`Action.answered`](/business/events/Action.answered) | Two-way: `try`, `send`, `do` | | [Action.ask](/business/nouns/action/ask) | Ask puts a Question to a Party, a Role, or a Worker and holds the Action `pending` with reason `awaitingInput`. | [Worker](/business/nouns/worker) | [`Action.asked`](/business/events/Action.asked) | Two-way: `try`, `send`, `do` | | [Action.attest](/business/nouns/action/attest) | Attest records a credentialed Human’s signed performance of a Reserved Act that an Action needs to finish. | [Legal Lead](/agents/legal/legal-lead) | [`Action.attested`](/business/events/Action.attested) | None. | | [Action.cancel](/business/nouns/action/cancel) | Cancel stops a pending Action, sets its status to `canceled`, and runs its compensation. | [Risk Analyst](/agents/operations/risk-analyst) | [`Action.canceled`](/business/events/Action.canceled) | None. | | [Action.evaluate](/business/nouns/action/evaluate) | Evaluate grades an Action’s output against a rubric and records the verdict as an Event. | [Quality Lead](/agents/quality/quality-lead) | [`Action.evaluated`](/business/events/Action.evaluated) | None. | | [Action.pause](/business/nouns/action/pause) | Pause holds a pending Action past the close of its delay window until a watcher resumes, redirects, or cancels it. | [Worker](/business/nouns/worker) | [`Action.paused`](/business/events/Action.paused) | None. | | [Action.redirect](/business/nouns/action/redirect) | Redirect changes a pending Action’s inputs or target inside its delay window, before it runs. | [Operations Lead](/agents/operations/operations-lead) | [`Action.redirected`](/business/events/Action.redirected) | None. | | [Action.resume](/business/nouns/action/resume) | Resume ends a pause and lets the Action run as reviewed, or reopen what remained of its delay window. | [Worker](/business/nouns/worker) | [`Action.resumed`](/business/events/Action.resumed) | None. | | [Action.retry](/business/nouns/action/retry) | Retry runs a failed Action again as a new Action linked to the one that failed. | [Reliability Engineer](/agents/engineering/reliability-engineer) | [`Action.retried`](/business/events/Action.retried) | None. | | [Action.create](/business/nouns/action/create) | Creates an Action. Inherited from [Noun](/business/nouns/noun). | None. | `Action.created` | Two-way: `try`, `send`, `do` | | [Action.get](/business/nouns/action/get) | Returns one Action by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Action.list](/business/nouns/action/list) | Returns Actions, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | An Action is kept forever and never edited: it has no `update` or `delete`. ## Events Events no Verb emits. Each Verb’s Event is in the Verbs table above; every Event is delivered in the same shape. ### Action.done An Action’s work finished and its effects are written. Raised by the runtime. | Field | Type | Required | Description | | --- | --- | --- | --- | | `name` | `string` | Yes | `Action.done`. | | `at` | `datetime` | Yes | When it happened. | | `seq` | `integer` | No | Its position in the namespace, one more than the Event before; any seq is a cursor into the history. | | `data` | `json` | Yes | The Thing as the Action left it. | | `data.action` | [Action](/business/nouns/action) | Yes | The Action as the change left it. | | `data.action.status` | `string` | Yes | One of `pending`, `done`, `failed`, `canceled`, or `refused`. | | `data.action.reason` | `string` | No | Why a pending Action waits: `queued`, `running`, `retrying`, `awaitingWorker`, `awaitingInput`, `awaitingSource`, `awaitingAction`, or `awaitingTime`. | | `data.action.mode` | `string` | Yes | How the caller invoked it: `try`, `send`, or `do`. | | `data.action.by` | [Worker](/business/nouns/worker) | No | The Worker that performed it. | | `data.action.for` | [Party](/business/nouns/party) | No | The Party it was done on behalf of. | | `data.action.via` | `string` | No | The Interface or request it arrived through. | | `data.action.on` | `string` | No | The Action or Event that caused it, such as the failed attempt a retry follows. | | `data.action.thing` | `string` | No | The record, at the Version the Action was decided against. | | `data.action.input` | `json` | No | The input it was called with. | | `data.action.createdAt` | `datetime` | No | When it was called. | | `data.action.reserved` | `money` | No | The most this Action may cost, held against its Limits from the check until it settles, billed misses included. | | `data.previous.status` | `string` | Yes | The `status` before this Event: `pending`. | ```json { "$id": "https://api.sb/quietcopy.com/events/event_1", "$type": "Event", "name": "Action.done", "at": "2026-10-22T12:00:00Z", "data": { "action": { "$id": "https://api.sb/quietcopy.com/actions/action_1", "$type": "Action", "status": "done", "reason": "queued", "mode": "try", "by": "worker_1", "for": "party_1", "via": "API", "on": "Invoice.overdue", "thing": "invoice_1@v3", "input": {}, "createdAt": "2026-10-22T12:00:00Z", "reserved": { "amount": 39, "currency": "USD" } }, "previous": { "status": "pending" } }, "seq": 1 } ``` ### Action.failed An Action stopped with an error before it finished; a retry is a new Action. Raised by the runtime. | Field | Type | Required | Description | | --- | --- | --- | --- | | `name` | `string` | Yes | `Action.failed`. | | `at` | `datetime` | Yes | When it happened. | | `seq` | `integer` | No | Its position in the namespace, one more than the Event before; any seq is a cursor into the history. | | `data` | `json` | Yes | The Thing as the Action left it. | | `data.action` | [Action](/business/nouns/action) | Yes | The Action as the change left it. | | `data.action.status` | `string` | Yes | One of `pending`, `done`, `failed`, `canceled`, or `refused`. | | `data.action.reason` | `string` | No | Why a pending Action waits: `queued`, `running`, `retrying`, `awaitingWorker`, `awaitingInput`, `awaitingSource`, `awaitingAction`, or `awaitingTime`. | | `data.action.mode` | `string` | Yes | How the caller invoked it: `try`, `send`, or `do`. | | `data.action.by` | [Worker](/business/nouns/worker) | No | The Worker that performed it. | | `data.action.for` | [Party](/business/nouns/party) | No | The Party it was done on behalf of. | | `data.action.via` | `string` | No | The Interface or request it arrived through. | | `data.action.on` | `string` | No | The Action or Event that caused it, such as the failed attempt a retry follows. | | `data.action.thing` | `string` | No | The record, at the Version the Action was decided against. | | `data.action.input` | `json` | No | The input it was called with. | | `data.action.createdAt` | `datetime` | No | When it was called. | | `data.action.reserved` | `money` | No | The most this Action may cost, held against its Limits from the check until it settles, billed misses included. | | `data.error` | `string` | Yes | The error it stopped with; its page gives the fix. | | `data.previous.status` | `string` | Yes | The `status` before this Event: `pending`. | ```json { "$id": "https://api.sb/quietcopy.com/events/event_1", "$type": "Event", "name": "Action.failed", "at": "2026-10-22T12:00:00Z", "data": { "action": { "$id": "https://api.sb/quietcopy.com/actions/action_1", "$type": "Action", "status": "failed", "reason": "queued", "mode": "try", "by": "worker_1", "for": "party_1", "via": "API", "on": "Invoice.overdue", "thing": "invoice_1@v3", "input": {}, "createdAt": "2026-10-22T12:00:00Z", "reserved": { "amount": 39, "currency": "USD" } }, "error": "conflict", "previous": { "status": "pending" } }, "seq": 1 } ``` ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Action.create` | Yes | Yes | Yes | No | | `Action.get` | Yes | Yes | Yes | Yes | | `Action.list` | Yes | Yes | Yes | Yes | | `Action.answer` | Yes | Yes | Yes | No | | `Action.ask` | Yes | Yes | Yes | No | | `Action.attest` | Yes | Yes | Yes | No | | `Action.cancel` | Yes | Yes | Yes | No | | `Action.evaluate` | Yes | Yes | Yes | No | | `Action.pause` | Yes | Yes | Yes | No | | `Action.redirect` | Yes | Yes | Yes | No | | `Action.resume` | Yes | Yes | Yes | No | | `Action.retry` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Cancel the latest action. ``` **API** ```bash curl -X POST https://api.sb/petpantry.shop/actions/action_1/cancel \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/petpantry.shop", "action": { "$id": "https://api.sb/petpantry.shop/actions/action_1", "$type": "Action", "status": "done", "mode": "try", "operation": "Action.cancel" }, "links": { "self": "https://api.sb/petpantry.shop/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const action = await $.Action.cancel({ action: 'action_1' }) ``` **CLI** ```bash npx startup-builder do Action.cancel --json '{"action":"action_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Action.cancel({ action: 'action_1' })" } } ``` ## Example Bea, the [Billing Specialist](/agents/finance/billing-specialist) at a voice-actor marketplace, runs [`Order.refund`](/business/nouns/order/refund) on a $90 [Order](/business/nouns/order). The Action records `by: Bea`, `for` the game studio that asked, `mode: do` and `status: Done`, and emits `Order.refunded`. # pause URL: /business/nouns/action/pause · Id: `verb:Action.pause` · Call: `await $.Action.pause({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Pause holds a pending Action past the close of its delay window until a watcher resumes, redirects, or cancels it. Pause holds a pending [Action](/business/nouns/action) past the close of its delay window until a watcher resumes, redirects, or cancels it. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `action` | [Action](/business/nouns/action) | Yes | The pending Action. | | `reason` | `text` | Yes | Why it must wait. | | `until` | `datetime` | No | When the pause escalates to the Role above if nobody resolves it; defaults to one business day. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `action` | [Action](/business/nouns/action) | Yes | The paused Action, still `pending`. | ## Effects - Emits [`Action.paused`](/business/events/Action.paused). - Records a Decision with the reason. - Escalates to the Role above the watcher when `until` passes unresolved. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Action.pause](/business/nouns/action/pause) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Pause the latest action. ``` **API** ```bash curl -X POST https://api.sb/tutorloop.com/actions/action_1/pause \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"reason":"Example reason"}' ``` ```json { "api": "https://api.sb/tutorloop.com", "action": { "$id": "https://api.sb/tutorloop.com/actions/action_1", "$type": "Action", "status": "done", "mode": "try", "operation": "Action.pause" }, "links": { "self": "https://api.sb/tutorloop.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const action = await $.Action.pause({ action: 'action_1', reason: 'Example reason' }) ``` **CLI** ```bash npx startup-builder do Action.pause --json '{"action":"action_1","reason":"Example reason"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Action.pause({ action: 'action_1', reason: 'Example reason' })" } } ``` # redirect URL: /business/nouns/action/redirect · Id: `verb:Action.redirect` · Call: `await $.Action.redirect({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Redirect changes a pending Action’s inputs or target inside its delay window, before it runs. Redirect changes a pending [Action](/business/nouns/action)’s inputs or target inside its delay window, before it runs. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `action` | [Action](/business/nouns/action) | Yes | The pending Action. | | `changes` | `json` | Yes | The inputs to replace. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `action` | [Action](/business/nouns/action) | Yes | The redirected Action. | ## Effects - Emits [`Action.redirected`](/business/events/Action.redirected). - Performed by the [Operations Lead](/agents/operations/operations-lead). ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The input does not match the schema of the operation. | [`invalid-input`](/code/api/errors/invalid-input) | Read the schema of the operation, then send every required field with the right type. | [Action.redirect](/business/nouns/action/redirect) | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Action.redirect](/business/nouns/action/redirect) | | The record is not in a state that allows this Verb, so the call is refused. | [`refused`](/code/api/errors/refused) | Read the record, run the Verb that moves it to an allowed state, then retry. | [Action.redirect](/business/nouns/action/redirect) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Redirect the latest action. ``` **API** ```bash curl -X POST https://api.sb/tutorloop.com/actions/action_1/redirect \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"changes":{}}' ``` ```json { "api": "https://api.sb/tutorloop.com", "action": { "$id": "https://api.sb/tutorloop.com/actions/action_1", "$type": "Action", "status": "done", "mode": "try", "operation": "Action.redirect" }, "links": { "self": "https://api.sb/tutorloop.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const action = await $.Action.redirect({ action: 'action_1', changes: {} }) ``` **CLI** ```bash npx startup-builder do Action.redirect --json '{"action":"action_1","changes":{}}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Action.redirect({ action: 'action_1', changes: {} })" } } ``` # resume URL: /business/nouns/action/resume · Id: `verb:Action.resume` · Call: `await $.Action.resume({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Resume ends a pause and lets the Action run as reviewed, or reopen what remained of its delay window. Resume ends a pause and lets the [Action](/business/nouns/action) run as reviewed, or reopen what remained of its delay window. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `action` | [Action](/business/nouns/action) | Yes | The paused Action. | | `reason` | `text` | Yes | Why it may proceed. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `action` | [Action](/business/nouns/action) | Yes | The resumed Action. | ## Effects - Emits [`Action.resumed`](/business/events/Action.resumed). - Records a Decision with the reason. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Action.resume](/business/nouns/action/resume) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Resume the latest action. ``` **API** ```bash curl -X POST https://api.sb/patentpad.com/actions/action_1/resume \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"reason":"Example reason"}' ``` ```json { "api": "https://api.sb/patentpad.com", "action": { "$id": "https://api.sb/patentpad.com/actions/action_1", "$type": "Action", "status": "done", "mode": "try", "operation": "Action.resume" }, "links": { "self": "https://api.sb/patentpad.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const action = await $.Action.resume({ action: 'action_1', reason: 'Example reason' }) ``` **CLI** ```bash npx startup-builder do Action.resume --json '{"action":"action_1","reason":"Example reason"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Action.resume({ action: 'action_1', reason: 'Example reason' })" } } ``` # retry URL: /business/nouns/action/retry · Id: `verb:Action.retry` · Call: `await $.Action.retry({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Retry runs a failed Action again as a new Action linked to the one that failed. Retry runs a failed [Action](/business/nouns/action) again as a new Action linked to the one that failed. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `action` | [Action](/business/nouns/action) | Yes | The failed Action. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `retry` | [Action](/business/nouns/action) | Yes | The new Action. | ## Effects - Emits [`Action.retried`](/business/events/Action.retried). - Performed by the [Reliability Engineer](/agents/engineering/reliability-engineer). ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Action.retry](/business/nouns/action/retry) | | The record is not in a state that allows this Verb, so the call is refused. | [`refused`](/code/api/errors/refused) | Read the record, run the Verb that moves it to an allowed state, then retry. | [Action.retry](/business/nouns/action/retry) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Retry the latest action. ``` **API** ```bash curl -X POST https://api.sb/tutorloop.com/actions/action_1/retry \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/tutorloop.com", "retry": { "$id": "https://api.sb/tutorloop.com/actions/action_1", "$type": "Action", "status": "pending", "mode": "try" }, "action": { "$id": "https://api.sb/tutorloop.com/actions/action_1", "operation": "Action.retry", "status": "done" }, "links": { "self": "https://api.sb/tutorloop.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const retry = await $.Action.retry({ action: 'action_1' }) ``` **CLI** ```bash npx startup-builder do Action.retry --json '{"action":"action_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Action.retry({ action: 'action_1' })" } } ``` # Ad URL: /business/nouns/ad · Id: `noun:ad` > An Ad is one paid or house placement promoting an Offer to an Audience, in a format such as search, display, or video. An Ad is one paid or house placement promoting an [Offer](/business/nouns/offer) to an [Audience](/business/nouns/audience), in a format such as search, display, or video. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `format` | `string` | Yes | One of `search`, `display`, `image`, or `video`. | | `spend` | `money` | No | What it has cost so far. | ## Object ```json { "$id": "https://api.sb/patentpad.com/ads/ad_1", "$type": "Ad", "format": "search", "spend": { "amount": 499, "currency": "USD" } } ``` ## Relationships - An Ad **promotes** one [Offer](/business/nouns/offer): each Ad sells one [Offer](/business/nouns/offer). `promotes`, inverse [`promotedBy`](/business/nouns/offer#rel-promoted-by). - An Ad **is run in** one [Campaign](/business/nouns/campaign): a [Campaign](/business/nouns/campaign) places Ads that share its budget and window. `runIn`, inverse [`runs`](/business/nouns/campaign#rel-runs). - An Ad **targets** many [Audiences](/business/nouns/audience): an Ad is shown to the people its [Audiences](/business/nouns/audience) select. `targets`, inverse [`targetedBy`](/business/nouns/audience#rel-targeted-by). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Ad.create](/business/nouns/ad/create) | Creates an Ad. Inherited from [Noun](/business/nouns/noun). | None. | `Ad.created` | Two-way: `try`, `send`, `do` | | [Ad.get](/business/nouns/ad/get) | Returns one Ad by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Ad.list](/business/nouns/ad/list) | Returns Ads, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Ad.update](/business/nouns/ad/update) | Changes the given properties of an Ad. Inherited from [Noun](/business/nouns/noun). | None. | `Ad.updated` | Two-way: `try`, `send`, `do` | | [Ad.delete](/business/nouns/ad/delete) | Deletes an Ad; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Ad.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Ad.create` | Yes | Yes | Yes | No | | `Ad.get` | Yes | Yes | Yes | Yes | | `Ad.list` | Yes | Yes | Yes | Yes | | `Ad.update` | Yes | Yes | Yes | No | | `Ad.delete` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Add an ad to ShiftNote. ``` **API** ```bash curl -X POST https://api.sb/shiftnote.app/ads \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"format":"search"}' ``` ```json { "api": "https://api.sb/shiftnote.app", "ad": { "$id": "https://api.sb/shiftnote.app/ads/ad_1", "$type": "Ad", "format": "search" }, "action": { "$id": "https://api.sb/shiftnote.app/actions/action_1", "operation": "Ad.create", "status": "done" }, "links": { "self": "https://api.sb/shiftnote.app/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const ad = await $.Ad.create({ format: 'search' }) ``` **CLI** ```bash npx startup-builder do Ad.create --json '{"format":"search"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Ad.create({ format: 'search' })" } } ``` ## Example A short-video Ad shows a meal-planning [App](/business/nouns/app) filling a week of dinners from one fridge photo. It targets an [Audience](/business/nouns/audience) of parents who save recipe posts, spends $40 a day, and links to the 7-day trial [Offer](/business/nouns/offer). # Agent URL: /business/nouns/agent · Id: `noun:agent` > An Agent is a digital worker with instructions, tools, and a model that performs Verbs for a Startup. An Agent is a digital worker with instructions, tools, and a model that performs [Verbs](/business/nouns/verb) for a [Startup](/business/nouns/startup). It acts from a [Role](/business/nouns/role) seat, under that Role’s [Permissions](/business/nouns/permission) and its own [Mandates](/business/nouns/mandate). ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `instructions` | `text` | Yes | What the Agent does and how. | | `model` | `string` | Yes | The model the Agent runs on. | | `tools` | `string[]` | No | The tools the Agent may call. | | `skills` | list of [Skill](/business/nouns/skill) | No | The Skills it loads. | | `memory` | `string` | No | One of `tenant` (one Memory per Customer Tenant) or `startup` (one Memory for the Startup). | | `maxSteps` | `integer` | No | The most steps one Task may take. | | `budget` | `money` | No | The most one Task may spend; the Mandate’s Limits apply as well. | | `handoffs` | list of [Role](/business/nouns/role) | No | The Roles it hands work to. | | `status` | `string` | Yes | One of `standby`, `seated`, `paused` or `retired`: whether it fills a Role and is working. | ## Object ```json { "$id": "https://api.sb/shiftnote.app/agents/agent_1", "$type": "Agent", "instructions": "Example instructions", "model": "Example model", "tools": [ "Example tools" ], "skills": [ "skill_1" ], "memory": "tenant", "maxSteps": 1, "budget": { "amount": 79, "currency": "USD" }, "handoffs": [ "role_1" ], "status": "standby" } ``` ## Relationships - An Agent **is employed by** many [Startups](/business/nouns/startup): an Agent holds a seat in the [Startup](/business/nouns/startup) and acts within the authority it grants; one Agent can hold seats in many Startups. `employedBy`, inverse [`employs`](/business/nouns/startup#rel-employs). - An Agent **has** many [Mandates](/business/nouns/mandate): a [Mandate](/business/nouns/mandate) lets an Agent act without asking each time, within its [Permissions](/business/nouns/permission) and [Limits](/business/nouns/limit), until it expires or is revoked. `mandates`, inverse [`authorizes`](/business/nouns/mandate#rel-authorizes). ## Lifecycle | State | Meaning | Moves to | | --- | --- | --- | | `standby` (first) | It fills no Role, so it performs no Verbs. | `seated` on [`Role.staffed`](/business/events/Role.staffed) when the Worker who fills the Role is this Agent | | `seated` | It fills at least one Role and performs that Role’s Verbs under its Permissions. | `standby` on [`Role.staffed`](/business/events/Role.staffed) when another Worker fills the last Role this Agent held; `paused` by [Agent.pause](/business/nouns/agent/pause); `retired` by [Agent.retire](/business/nouns/agent/retire) | | `paused` | It keeps its seats, Memory, Mandates and Limits, and starts no new Action until it resumes. | `seated` by [Agent.resume](/business/nouns/agent/resume); `retired` by [Agent.retire](/business/nouns/agent/retire) | | `retired` | It holds no seat in the Startup again; its Actions, Memory and Mailbox history stay on the record. | None: it ends here. | ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Dispute.accept](/business/nouns/dispute/accept) | Accept concedes an open Dispute without contest, so the buyer keeps the held amount and the Dispute closes. | [Billing Specialist](/agents/finance/billing-specialist) | [`Dispute.accepted`](/business/events/Dispute.accepted) | One-way (money): `send`, `do` | | [Incident.acknowledge](/business/nouns/incident/acknowledge) | Acknowledge records that an on-call Worker owns an open Incident and stops its escalation. | [Reliability Engineer](/agents/engineering/reliability-engineer) | [`Incident.acknowledged`](/business/events/Incident.acknowledged) | Two-way: `try`, `send`, `do` | | [Customer.activate](/business/nouns/customer/activate) | Activate marks a Customer activated on an Offer once its declared activation Event reaches the count within the window. | [Analyst](/agents/marketing/analyst) | [`Customer.activated`](/business/events/Customer.activated) | Two-way: `try`, `send`, `do` | | [SSOConnection.activate](/business/nouns/sso-connection/activate) | Activate turns an SSO Connection on after a test sign-in passes, so the Tenant’s people sign in through it. | [Security Engineer](/agents/engineering/security-engineer) | [`SSOConnection.activated`](/business/events/SSOConnection.activated) | Two-way: `try`, `send`, `do` | | [Waitlist.admit](/business/nouns/waitlist/admit) | Admit releases Leads from a Waitlist to the Offer they waited for, in the order the Waitlist ranks them. | [Sales Lead](/agents/sales/sales-lead) | [`Waitlist.admitted`](/business/events/Waitlist.admitted) | None. | | [Registration.admit](/business/nouns/registration/admit) | Admit gives the next Contact in line a place at a Gathering when one frees up or its capacity rises. | [Marketing Lead](/agents/marketing/marketing-lead) | [`Registration.admitted`](/business/events/Registration.admitted) | Two-way: `try`, `send`, `do` | | [Startup.advance](/business/nouns/startup/advance) | Advance moves a Startup to its next Lifecycle state once every entry check of that state passes. | [Agent](/business/nouns/agent) | [`Startup.advanced`](/business/events/Startup.advanced) | None. | | [Deal.advance](/business/nouns/deal/advance) | Advance moves a Deal to its next stage once every field that stage requires is filled. | [Sales Lead](/agents/sales/sales-lead) | [`Deal.advanced`](/business/events/Deal.advanced) | Two-way: `try`, `send`, `do` | | [Conversation.answer](/business/nouns/conversation/answer) | Answer replies in a Conversation through the Channel it arrived on and closes the reply Task it opened. | [Customer Lead](/agents/customer/customer-lead) | [`Conversation.answered`](/business/events/Conversation.answered) | None. | | [CreditGrant.apply](/business/nouns/credit-grant/apply) | Apply spends Credit Grants against a finalizing Invoice, promotional first, then by priority and earliest expiry, and settles them through Stripe credit grants. | [Billing Specialist](/agents/finance/billing-specialist) | [`CreditGrant.applied`](/business/events/CreditGrant.applied) | Two-way: `try`, `send`, `do` | | [Approval.approve](/business/nouns/approval/approve) | Approve allows the pending Action an Approval holds, and that Action runs. | [Founder](/agents/founding/founder) | [`Approval.approved`](/business/events/Approval.approved) | None. | | [Bill.approve](/business/nouns/bill/approve) | Approve accepts a coded Bill for payment within the approver’s Mandate and schedules it for its due date. | [Finance Lead](/agents/finance/finance-lead) | [`Bill.approved`](/business/events/Bill.approved) | One-way (money): `send`, `do` | | [Registration.approve](/business/nouns/registration/approve) | Approve gives a requested place at a Gathering to the Contact who asked, or a place in line when the Gathering is full. | [Marketing Lead](/agents/marketing/marketing-lead) | [`Registration.approved`](/business/events/Registration.approved) | Two-way: `try`, `send`, `do` | | [PayRun.approve](/business/nouns/pay-run/approve) | Approve accepts a prepared Pay Run within the approver’s Mandate, books its cost, and schedules payment to land on the pay date. | [Payroll Specialist](/agents/people/payroll-specialist) | [`PayRun.approved`](/business/events/PayRun.approved) | One-way (money): `send`, `do` | | [Dashboard.ask](/business/nouns/dashboard/ask) | Ask answers a plain-language question with a query over the Startup’s records and shows the query beside the result. | [Analyst](/agents/marketing/analyst) | [`Dashboard.asked`](/business/events/Dashboard.asked) | Two-way: `try`, `send`, `do` | | [Risk.assess](/business/nouns/risk/assess) | Assess scores a Risk’s likelihood and impact from the Startup’s records and sets its next review date. | [Risk Analyst](/agents/operations/risk-analyst) | [`Risk.assessed`](/business/events/Risk.assessed) | Two-way: `try`, `send`, `do` | | [Task.assign](/business/nouns/task/assign) | Assign gives a Task to a Worker, human or agent, and places it in that Worker’s worklist. | [Product Lead](/agents/product/product-lead) | [`Task.assigned`](/business/events/Task.assigned) | None. | | [Lead.assign](/business/nouns/lead/assign) | Assign gives a Lead one owner Worker, by round robin, territory or ICP fit, as the Startup’s routing Policy says. | [Sales Lead](/agents/sales/sales-lead) | [`Lead.assigned`](/business/events/Lead.assigned) | Two-way: `try`, `send`, `do` | | [Deal.assign](/business/nouns/deal/assign) | Assign gives a Deal one owner Worker, who carries its next step until it is won or lost. | [Sales Lead](/agents/sales/sales-lead) | [`Deal.assigned`](/business/events/Deal.assigned) | Two-way: `try`, `send`, `do` | | [Conversation.assign](/business/nouns/conversation/assign) | Assign routes a Conversation to the Worker holding the right Role, by topic, Customer tier and language. | [Customer Lead](/agents/customer/customer-lead) | [`Conversation.assigned`](/business/events/Conversation.assigned) | Two-way: `try`, `send`, `do` | | [Transaction.attach](/business/nouns/transaction/attach) | Attach matches a receipt File to a card Transaction, or flags the Transaction when no receipt arrives in time. | [Finance Lead](/agents/finance/finance-lead) | [`Transaction.attached`](/business/events/Transaction.attached) | Two-way: `try`, `send`, `do` | | [Registration.attend](/business/nouns/registration/attend) | Attend records that a registered Contact joined the Gathering; an online room calls it on join. | [Marketing Lead](/agents/marketing/marketing-lead) | [`Registration.attended`](/business/events/Registration.attended) | Two-way: `try`, `send`, `do` | | [Domain.authenticate](/business/nouns/domain/authenticate) | Authenticate writes a Domain’s SPF, DKIM and DMARC records and verifies them before its first send. | [Security Engineer](/agents/engineering/security-engineer) | [`Domain.authenticated`](/business/events/Domain.authenticated) | Two-way: `try`, `send`, `do` | | [Mandate.authorize](/business/nouns/mandate/authorize) | Authorize grants an Agent a standing Mandate to perform a Verb within a Limit, without asking each time. | [Treasurer](/agents/finance/treasurer) | [`Mandate.authorized`](/business/events/Mandate.authorized) | One-way (money): `send`, `do` | | [Domain.benchmark](/business/nouns/domain/benchmark) | Benchmark measures a Domain’s estimated traffic, ranking Keywords, authority and referring domains beside the competitors named. | [Analyst](/agents/marketing/analyst) | [`Domain.benchmarked`](/business/events/Domain.benchmarked) | Two-way: `try`, `send`, `do` | | [Invoice.bill](/business/nouns/invoice/bill) | Bill finalizes an Invoice and presents it to the Customer for payment. | [Billing Specialist](/agents/finance/billing-specialist) | [`Invoice.billed`](/business/events/Invoice.billed) | One-way (customer): `send`, `do` | | [Meeting.book](/business/nouns/meeting/book) | Book schedules a Meeting with a Contact at a time both calendars hold free. | [Sales Engineer](/agents/sales/sales-engineer) | [`Meeting.booked`](/business/events/Meeting.booked) | None. | | [Message.broadcast](/business/nouns/message/broadcast) | Broadcast sends one Message to an Audience, now or at a set time, split by Variant when an Experiment runs. | [Marketing Lead](/agents/marketing/marketing-lead) | [`Message.broadcasted`](/business/events/Message.broadcasted) | One-way (brand, customer): `send`, `do` | | [Startup.build](/business/nouns/startup/build) | Build provisions the Systems, Sites and Interfaces a Startup’s definition declares, and moves the Startup to Building. | [Engineering Lead](/agents/engineering/engineering-lead) | [`Startup.built`](/business/events/Startup.built) | None. | | Fund.call | Call draws capital from every investor pro rata to their Capital Commitment, due by a date, and records the Capital Call. | [Treasurer](/agents/finance/treasurer) | `Fund.called` | One-way (money): `send`, `do` | | [Integration.call](/business/nouns/integration/call) | Call sends one request to an upstream through an Integration, with its token filled in server-side, for endpoints no Mapping covers. | [Integration Engineer](/agents/engineering/integration-engineer) | [`Integration.called`](/business/events/Integration.called) | One-way (customer): `send`, `do` | | [Action.cancel](/business/nouns/action/cancel) | Cancel stops a pending Action, sets its status to `canceled`, and runs its compensation. | [Risk Analyst](/agents/operations/risk-analyst) | [`Action.canceled`](/business/events/Action.canceled) | None. | | [Instrument.cancel](/business/nouns/instrument/cancel) | Cancel ends an unvested, expired or forfeited Instrument and returns any option Shares to the pool. | [Legal Lead](/agents/legal/legal-lead) | [`Instrument.canceled`](/business/events/Instrument.canceled) | One-way: `send`, `do` | | [Enrollment.cancel](/business/nouns/enrollment/cancel) | Cancel ends one Contact’s run through a Sequence for good, with the reason it records as `exitReason`. | [Prospector](/agents/sales/prospector) | [`Enrollment.canceled`](/business/events/Enrollment.canceled) | Two-way: `try`, `send`, `do` | | [Event.capture](/business/nouns/event/capture) | Capture records an Event from a Site, App or API call that no Verb emits, such as a page view or a click. | [Analyst](/agents/marketing/analyst) | [`Event.captured`](/business/events/Event.captured) | Two-way: `try`, `send`, `do` | | [Transaction.categorize](/business/nouns/transaction/categorize) | Categorize codes a Transaction to an account in the chart by the Startup’s Policy and flags a low-confidence code for review. | [Finance Lead](/agents/finance/finance-lead) | [`Transaction.categorized`](/business/events/Transaction.categorized) | Two-way: `try`, `send`, `do` | | [Monitor.check](/business/nouns/monitor/check) | Check runs a Monitor once now from several regions and records the result as an Event. | [Reliability Engineer](/agents/engineering/reliability-engineer) | [`Monitor.checked`](/business/events/Monitor.checked) | Two-way: `try`, `send`, `do` | | [Entitlement.check](/business/nouns/entitlement/check) | Check says whether a Customer may call a Verb now, how much of its Limit remains, when that resets, and which Offer lifts it. | [Agent](/business/nouns/agent) | [`Entitlement.checked`](/business/events/Entitlement.checked) | Two-way: `try`, `send`, `do` | | [Domain.claim](/business/nouns/domain/claim) | Claim gives a Startup a one-label name under an issuing Domain, or assigns it a held Domain through an approved Change. | [Engineering Lead](/agents/engineering/engineering-lead) | [`Domain.claimed`](/business/events/Domain.claimed) | Two-way: `try`, `send`, `do` | | [Brand.clear](/business/nouns/brand/clear) | Clear checks a proposed Brand name against trademark registers, Domain availability and the Startup’s handles on outside platforms in one call. | [Legal Lead](/agents/legal/legal-lead) | [`Brand.cleared`](/business/events/Brand.cleared) | Two-way: `try`, `send`, `do` | | [Startup.clone](/business/nouns/startup/clone) | Clone copies a Startup’s definition into a new Startup once, with no link back to the source. | [Agent](/business/nouns/agent) | [`Startup.cloned`](/business/events/Startup.cloned) | None. | | [Voice.clone](/business/nouns/voice/clone) | Clone trains a Voice from a real speaker’s recordings after the speaker records Consent in that same voice. | [Content Lead](/agents/marketing/content-lead) | [`Voice.cloned`](/business/events/Voice.cloned) | Two-way: `try`, `send`, `do` | | [Period.close](/business/nouns/period/close) | Close ends a month’s books once every Entry in the Period is reconciled, and makes its statements final. | [Finance Lead](/agents/finance/finance-lead) | [`Period.closed`](/business/events/Period.closed) | Two-way: `try`, `send`, `do` | | [Risk.close](/business/nouns/risk/close) | Close ends a Risk that can no longer happen and keeps it, with its scores and treatments, forever. | [Risk Analyst](/agents/operations/risk-analyst) | [`Risk.closed`](/business/events/Risk.closed) | One-way: `send`, `do` | | [Conversation.close](/business/nouns/conversation/close) | Close marks a Conversation resolved, confirmed by the Customer or assumed after 72 hours with no reply. | [Customer Lead](/agents/customer/customer-lead) | [`Conversation.closed`](/business/events/Conversation.closed) | Two-way: `try`, `send`, `do` | | [Invoice.collect](/business/nouns/invoice/collect) | Collect charges a Customer’s saved payment method for an open Invoice and retries on failure. | [Billing Specialist](/agents/finance/billing-specialist) | [`Invoice.collected`](/business/events/Invoice.collected) | One-way (money, customer): `send`, `do` | | [PlayMix.compile](/business/nouns/play-mix/compile) | Compile builds the next Play Mix from the Demand Budget, each Play’s ledger and last week’s Acquisitions, and records the diff. | [Marketing Lead](/agents/marketing/marketing-lead) | [`PlayMix.compiled`](/business/events/PlayMix.compiled) | Two-way: `try`, `send`, `do` | | [Experiment.conclude](/business/nouns/experiment/conclude) | Conclude ends an Experiment with a decision to ship, kill, or iterate, recorded as a Decision. | [Strategist](/agents/founding/strategist) | [`Experiment.concluded`](/business/events/Experiment.concluded) | None. | | [Domain.connect](/business/nouns/domain/connect) | Connect attaches a hostname a Startup already holds and verifies ownership through DNS. | [Integration Engineer](/agents/engineering/integration-engineer) | [`Domain.connected`](/business/events/Domain.connected) | Two-way: `try`, `send`, `do` | | [Integration.connect](/business/nouns/integration/connect) | Connect asks an account holder to approve an outside account for one System and records the grants they approve. | [Integration Engineer](/agents/engineering/integration-engineer) | [`Integration.connected`](/business/events/Integration.connected) | Two-way: `try`, `send`, `do` | | [Handle.connect](/business/nouns/handle/connect) | Connect binds a Handle to the Integration credential it publishes through, once the platform confirms the account. | [Content Lead](/agents/marketing/content-lead) | [`Handle.connected`](/business/events/Handle.connected) | Two-way: `try`, `send`, `do` | | [Lead.convert](/business/nouns/lead/convert) | Convert ends a qualified Lead’s pursuit as a Lead: it opens a Deal or routes the Lead to self-serve checkout. | [Sales Lead](/agents/sales/sales-lead) | [`Lead.converted`](/business/events/Lead.converted) | Two-way: `try`, `send`, `do` | | [Instrument.convert](/business/nouns/instrument/convert) | Convert turns a SAFE or note into Shares at a priced round, at its cap or discount, whichever gives more Shares. | [Legal Lead](/agents/legal/legal-lead) | [`Instrument.converted`](/business/events/Instrument.converted) | One-way (money): `send`, `do` | | CapitalCommitment.countersign | Countersign accepts an investor’s Capital Commitment once their subscription Agreement and accreditation check pass. | [Treasurer](/agents/finance/treasurer) | `CapitalCommitment.countersigned` | One-way: `send`, `do` | | [SSOConnection.deactivate](/business/nouns/sso-connection/deactivate) | Deactivate turns an SSO Connection off, so nobody signs in through it; its configuration is kept. | [Security Engineer](/agents/engineering/security-engineer) | [`SSOConnection.deactivated`](/business/events/SSOConnection.deactivated) | Two-way: `try`, `send`, `do` | | [MemberDirectory.deactivate](/business/nouns/member-directory/deactivate) | Deactivate stops a Member Directory’s pushes; everyone it added keeps their Roles until an admin removes them. | [Security Engineer](/agents/engineering/security-engineer) | [`MemberDirectory.deactivated`](/business/events/MemberDirectory.deactivated) | Two-way: `try`, `send`, `do` | | [Metric.define](/business/nouns/metric/define) | Define compiles a Metric’s query against the Startup’s Events and Entries and lists every Event it reads. | [Analyst](/agents/marketing/analyst) | [`Metric.defined`](/business/events/Metric.defined) | Two-way: `try`, `send`, `do` | | [Task.delegate](/business/nouns/task/delegate) | Delegate passes a Task to another Role along a declared handoff and keeps its history. | [Operations Lead](/agents/operations/operations-lead) | [`Task.delegated`](/business/events/Task.delegated) | None. | | [Order.deliver](/business/nouns/order/deliver) | Deliver hands the finished work of a Service Order to its Customer and opens the acceptance window. | [Delivery Manager](/agents/operations/delivery-manager) | [`Order.delivered`](/business/events/Order.delivered) | Two-way: `try`, `send`, `do` | | [Version.deploy](/business/nouns/version/deploy) | Deploy points a Startup’s live address at a Version, so every Interface serves that build. | [Engineering Lead](/agents/engineering/engineering-lead) | [`Version.deployed`](/business/events/Version.deployed) | None. | | [MemberDirectory.deprovision](/business/nouns/member-directory/deprovision) | Deprovision ends one person’s access to a Tenant in one Action when the Customer’s directory removes them. | [Security Engineer](/agents/engineering/security-engineer) | [`MemberDirectory.deprovisioned`](/business/events/MemberDirectory.deprovisioned) | Two-way: `try`, `send`, `do` | | [Lead.disqualify](/business/nouns/lead/disqualify) | Disqualify ends a Lead’s pursuit because it fits no Offer, with the reason; its Contact record and Consent stay. | [Sales Lead](/agents/sales/sales-lead) | [`Lead.disqualified`](/business/events/Lead.disqualified) | Two-way: `try`, `send`, `do` | | [Company.dissolve](/business/nouns/company/dissolve) | Dissolve winds up a Company that holds no business: it files final returns and the certificate, and keeps every record. | [Legal Lead](/agents/legal/legal-lead) | [`Company.dissolved`](/business/events/Company.dissolved) | One-way (money, customer): `send`, `do` | | Fund.distribute | Distribute returns cash or Shares to a Fund’s investors, split by the waterfall in its Agreement. | [Treasurer](/agents/finance/treasurer) | `Fund.distributed` | One-way (money): `send`, `do` | | [Video.draft](/business/nouns/video/draft) | Draft writes a Video’s timeline from a Startup’s records, its Brand and a Template, with a draft mark on every frame. | [Video Producer](/agents/marketing/video-producer) | [`Video.drafted`](/business/events/Video.drafted) | None. | | [Content.draft](/business/nouns/content/draft) | Draft writes Content of one kind from a brief, such as an article for a question the help center could not answer. | [Content Lead](/agents/marketing/content-lead) | [`Content.drafted`](/business/events/Content.drafted) | Two-way: `try`, `send`, `do` | | [RecoveryObjective.drill](/business/nouns/recovery-objective/drill) | Drill restores one Capability’s records into an isolated namespace and records whether the restore met both objectives. | [Reliability Engineer](/agents/engineering/reliability-engineer) | [`RecoveryObjective.drilled`](/business/events/RecoveryObjective.drilled) | Two-way: `try`, `send`, `do` | | [Hypothesis.drop](/business/nouns/hypothesis/drop) | Drop retires a Hypothesis from active work and keeps it, with its Evidence, on record. | [Strategist](/agents/founding/strategist) | [`Hypothesis.dropped`](/business/events/Hypothesis.dropped) | None. | | [File.edit](/business/nouns/file/edit) | Edit makes a new File from an existing one by instruction, such as upscaling or animating a still, and leaves the source unchanged. | [Content Lead](/agents/marketing/content-lead) | [`File.edited`](/business/events/File.edited) | Two-way: `try`, `send`, `do` | | [Process.enable](/business/nouns/process/enable) | Enable turns a Process on for a Startup, so its Workflows start on their Triggers. | [Founder](/agents/founding/founder) | [`Process.enabled`](/business/events/Process.enabled) | Two-way: `try`, `send`, `do` | | [Prospect.engage](/business/nouns/prospect/engage) | Engage records a Prospect’s first reply or raised hand and makes it a Lead that keeps its Acquisition. | [Prospector](/agents/sales/prospector) | [`Prospect.engaged`](/business/events/Prospect.engaged) | Two-way: `try`, `send`, `do` | | [Contact.enrich](/business/nouns/contact/enrich) | Enrich fills a Contact’s missing fields from outside sources and marks each value with where it came from. | [Prospector](/agents/sales/prospector) | [`Contact.enriched`](/business/events/Contact.enriched) | None. | | [Contact.enroll](/business/nouns/contact/enroll) | Enroll adds a Contact to a Sequence, which sends its steps until the Contact replies or exits. | [Prospector](/agents/sales/prospector) | [`Contact.enrolled`](/business/events/Contact.enrolled) | None. | | [Market.enter](/business/nouns/market/enter) | Enter opens a Market to a Startup: Prices in its currency, the Site in its locales, and its floor rows woken. | [Finance Lead](/agents/finance/finance-lead) | [`Market.entered`](/business/events/Market.entered) | One-way (money): `send`, `do` | | [Task.escalate](/business/nouns/task/escalate) | Escalate moves a Task to the Role its current Role escalates to, with the reason attached. | [Operations Lead](/agents/operations/operations-lead) | [`Task.escalated`](/business/events/Task.escalated) | None. | | [Conversation.escalate](/business/nouns/conversation/escalate) | Escalate hands a Conversation and its summary to the Worker in the Role above, a Human only where one holds it. | [Customer Lead](/agents/customer/customer-lead) | [`Conversation.escalated`](/business/events/Conversation.escalated) | Two-way: `try`, `send`, `do` | | [Issue.estimate](/business/nouns/issue/estimate) | Estimate records the effort an Issue needs, in days, so a week holds only what fits. | [Engineering Lead](/agents/engineering/engineering-lead) | [`Issue.estimated`](/business/events/Issue.estimated) | Two-way: `try`, `send`, `do` | | [Action.evaluate](/business/nouns/action/evaluate) | Evaluate grades an Action’s output against a rubric and records the verdict as an Event. | [Quality Lead](/agents/quality/quality-lead) | [`Action.evaluated`](/business/events/Action.evaluated) | None. | | [Flag.evaluate](/business/nouns/flag/evaluate) | Evaluate returns the Variant a Flag assigns one unit, the same one every time, and records the Exposure with every option and its propensity. | [Agent](/business/nouns/agent) | [`Flag.evaluated`](/business/events/Flag.evaluated) | None. | | [Customer.exempt](/business/nouns/customer/exempt) | Exempt records a Customer’s exemption or resale certificate, verifies it, and stops tax on its Orders where the certificate applies. | [Finance Lead](/agents/finance/finance-lead) | [`Customer.exempted`](/business/events/Customer.exempted) | Two-way: `try`, `send`, `do` | | [Instrument.exercise](/business/nouns/instrument/exercise) | Exercise buys the Shares an option or warrant covers at its strike price, up to what has vested. | [Legal Lead](/agents/legal/legal-lead) | [`Instrument.exercised`](/business/events/Instrument.exercised) | One-way (money): `send`, `do` | | [Quote.expire](/business/nouns/quote/expire) | Expire closes a sent Quote that reached its validUntil date unaccepted; it never converts afterward. | [Sales Engineer](/agents/sales/sales-engineer) | [`Quote.expired`](/business/events/Quote.expired) | Two-way: `try`, `send`, `do` | | [Collection.export](/business/nouns/collection/export) | Export writes a Collection’s records to a file or the Startup’s warehouse, once or on a schedule. | [Data Engineer](/agents/engineering/data-engineer) | [`Collection.exported`](/business/events/Collection.exported) | Two-way: `try`, `send`, `do` | | [Template.extend](/business/nouns/template/extend) | Extend adds a Template to a Startup’s bases, pinned to a Version, so the Startup inherits its definition. | [Agent](/business/nouns/agent) | [`Template.extended`](/business/events/Template.extended) | None. | | [StartupTemplate.extend](/business/nouns/startup-template/extend) | Extend adds a Startup Template to a Startup’s bases, pinned to a Version, so the Startup inherits its definition. | [Founder](/agents/founding/founder) | [`StartupTemplate.extended`](/business/events/StartupTemplate.extended) | Two-way: `try`, `send`, `do` | | [Video.finalize](/business/nouns/video/finalize) | Finalize lifts a Video’s draft mark once every claim it makes reads from a live record, so its cuts can be published. | [Video Producer](/agents/marketing/video-producer) | [`Video.finalized`](/business/events/Video.finalized) | None. | | [Visitor.forget](/business/nouns/visitor/forget) | Forget masks a person’s captured data across every Event and Recording and suppresses further capture, keeping the records. | [Privacy Officer](/agents/legal/privacy-officer) | [`Visitor.forgotten`](/business/events/Visitor.forgotten) | One-way (customer): `send`, `do` | | [Order.fulfill](/business/nouns/order/fulfill) | Fulfill grants what an Order bought: Entitlements for software and data, a shipment for goods. | [Delivery Manager](/agents/operations/delivery-manager) | [`Order.fulfilled`](/business/events/Order.fulfilled) | Two-way: `try`, `send`, `do` | | [File.generate](/business/nouns/file/generate) | Generate makes an image, video, speech or music File from a prompt and reference Files, and records how it was made. | [Content Lead](/agents/marketing/content-lead) | [`File.generated`](/business/events/File.generated) | Two-way: `try`, `send`, `do` | | [Instrument.grant](/business/nouns/instrument/grant) | Grant gives a Holder an option from the pool, with its strike price, vesting schedule and cliff. | [Legal Lead](/agents/legal/legal-lead) | [`Instrument.granted`](/business/events/Instrument.granted) | One-way: `send`, `do` | | [Offer.grant](/business/nouns/offer/grant) | Grant adds an Entitlement to an Offer: a Verb its Customers may call, optionally bounded by a Limit. | [Product Lead](/agents/product/product-lead) | [`Offer.granted`](/business/events/Offer.granted) | Two-way: `try`, `send`, `do` | | [Human.hold](/business/nouns/human/hold) | Hold sets aside part of a supplying Human’s earned balance against an open Dispute or an Order inside its clearance period. | [Billing Specialist](/agents/finance/billing-specialist) | [`Human.held`](/business/events/Human.held) | Two-way: `try`, `send`, `do` | | [Visitor.identify](/business/nouns/visitor/identify) | Identify joins a Visitor to the Contact it turns out to be, so earlier Visits count toward that person. | [Analyst](/agents/marketing/analyst) | [`Visitor.identified`](/business/events/Visitor.identified) | Two-way: `try`, `send`, `do` | | [Startup.import](/business/nouns/startup/import) | Import builds a new Startup from an existing business’s definition: its Offers, Pages, Nouns and Processes. | [Integration Engineer](/agents/engineering/integration-engineer) | [`Startup.imported`](/business/events/Startup.imported) | None. | | [Company.incorporate](/business/nouns/company/incorporate) | Incorporate forms a Company in a chosen jurisdiction, with its founders, shares and registered agent on record. | [Founder](/agents/founding/founder) | [`Company.incorporated`](/business/events/Company.incorporated) | One-way (money): `send`, `do` | | [Human.invite](/business/nouns/human/invite) | Invite asks a person to join a Startup in a named Role, sharing that Role’s work with its Agent. | [Recruiter](/agents/people/recruiter) | [`Human.invited`](/business/events/Human.invited) | None. | | [Share.issue](/business/nouns/share/issue) | Issue records new Shares of one class to a Holder under a board-approved Agreement, with the certificate or book entry. | [Legal Lead](/agents/legal/legal-lead) | [`Share.issued`](/business/events/Share.issued) | One-way (money): `send`, `do` | | [CreditGrant.issue](/business/nouns/credit-grant/issue) | Issue gives a Customer a paid or promotional Credit Grant that its metered calls draw down before anything is invoiced. | [Billing Specialist](/agents/finance/billing-specialist) | [`CreditGrant.issued`](/business/events/CreditGrant.issued) | Two-way: `try`, `send`, `do` | | [Card.issue](/business/nouns/card/issue) | Issue creates a Card under a Mandate once the Mandate check passes, with explicit limits on every interval. | [Treasurer](/agents/finance/treasurer) | [`Card.issued`](/business/events/Card.issued) | Two-way: `try`, `send`, `do` | | [APIKey.issue](/business/nouns/api-key/issue) | Issue creates an API Key for one Customer and returns its secret once; afterwards only the prefix shows. | [Agent](/business/nouns/agent) | [`APIKey.issued`](/business/events/APIKey.issued) | Two-way: `try`, `send`, `do` | | [Startup.launch](/business/nouns/startup/launch) | Launch puts a Startup live on its domain, serving its Offers to Customers. | [Founder](/agents/founding/founder) | [`Startup.launched`](/business/events/Startup.launched) | None. | | [Period.lock](/business/nouns/period/lock) | Lock seals a closed Period, so any later correction posts to the next open Period. | [Finance Lead](/agents/finance/finance-lead) | [`Period.locked`](/business/events/Period.locked) | One-way (money): `send`, `do` | | [Deal.lose](/business/nouns/deal/lose) | Lose closes a Deal as lost and records the reason the buyer gave. | [Sales Lead](/agents/sales/sales-lead) | [`Deal.lost`](/business/events/Deal.lost) | None. | | [Keyword.measure](/business/nouns/keyword/measure) | Measure records a Keyword’s monthly search volume, difficulty, cost per click and trend in one locale. | [Analyst](/agents/marketing/analyst) | [`Keyword.measured`](/business/events/Keyword.measured) | Two-way: `try`, `send`, `do` | | [Change.merge](/business/nouns/change/merge) | Merge applies a Change to live data with a three-way, field-level merge against its base Version. | [Engineering Lead](/agents/engineering/engineering-lead) | [`Change.merged`](/business/events/Change.merged) | None. | | [Visitor.merge](/business/nouns/visitor/merge) | Merge joins two Visitor ids that belong to one person and keeps both as aliases. | [Analyst](/agents/marketing/analyst) | [`Visitor.merged`](/business/events/Visitor.merged) | Two-way: `try`, `send`, `do` | | [Contact.merge](/business/nouns/contact/merge) | Merge joins a duplicate Contact into another, keeping every link, Message and Event on the one that remains. | [Sales Lead](/agents/sales/sales-lead) | [`Contact.merged`](/business/events/Contact.merged) | One-way: `send`, `do` | | [Organization.merge](/business/nouns/organization/merge) | Merge joins a duplicate Organization into another, keeping every Contact, Deal and Event on the one that remains. | [Sales Lead](/agents/sales/sales-lead) | [`Organization.merged`](/business/events/Organization.merged) | One-way: `send`, `do` | | [Agent.mint](/business/nouns/agent/mint) | Mint creates an Agent in a Customer’s Tenant from an Agent Product the Customer bought. | [People Lead](/agents/people/people-lead) | [`Agent.minted`](/business/events/Agent.minted) | None. | | [Lead.nurture](/business/nouns/lead/nurture) | Nurture takes a Lead that is not ready to buy off its owner’s queue and onto a Sequence, until it raises a hand again. | [Sales Lead](/agents/sales/sales-lead) | [`Lead.nurtured`](/business/events/Lead.nurtured) | Two-way: `try`, `send`, `do` | | [Human.onboard](/business/nouns/human/onboard) | Onboard admits a recruited Human to supply work once their identity, Credentials and payout details verify. | [Supply Manager](/agents/operations/supply-manager) | [`Human.onboarded`](/business/events/Human.onboarded) | None. | | [Renewal.open](/business/nouns/renewal/open) | Open starts the Renewal for a term Subscription before its term ends, with a usage review and any notice the legal floor requires. | [Success Manager](/agents/customer/success-manager) | [`Renewal.opened`](/business/events/Renewal.opened) | Two-way: `try`, `send`, `do` | | [Incident.open](/business/nouns/incident/open) | Open starts an Incident from a failing Monitor, an error spike or a Metric past its threshold, and pages the on-call Worker. | [Reliability Engineer](/agents/engineering/reliability-engineer) | [`Incident.opened`](/business/events/Incident.opened) | Two-way: `try`, `send`, `do` | | [Startup.pause](/business/nouns/startup/pause) | Pause moves a Startup to Dormant: its scheduled Workflows stop, and its Sites and records stay in place. | [Founder](/agents/founding/founder) | [`Startup.paused`](/business/events/Startup.paused) | None. | | [Process.pause](/business/nouns/process/pause) | Pause stops a Process from starting new Actions; Actions already in progress finish. | [Founder](/agents/founding/founder) | [`Process.paused`](/business/events/Process.paused) | Two-way: `try`, `send`, `do` | | [Enrollment.pause](/business/nouns/enrollment/pause) | Pause stops one Contact’s run through a Sequence at its current step, without ending it. | [Prospector](/agents/sales/prospector) | [`Enrollment.paused`](/business/events/Enrollment.paused) | Two-way: `try`, `send`, `do` | | [Agent.pause](/business/nouns/agent/pause) | Pause stops one Agent, every Agent on a Team, or every customer-facing Agent from starting new Actions in a Startup. | [Founder](/agents/founding/founder) | [`Agent.paused`](/business/events/Agent.paused) | Two-way: `try`, `send`, `do` | | [Commission.pay](/business/nouns/commission/pay) | Pay transfers a Commission’s earned, unpaid amount to the Partner’s connected account through Stripe. | [Billing Specialist](/agents/finance/billing-specialist) | [`Commission.paid`](/business/events/Commission.paid) | One-way (money): `send`, `do` | | [Bill.pay](/business/nouns/bill/pay) | Pay sends an approved Bill’s amount to its Organization on the due date and reconciles the payment to Entries. | [Treasurer](/agents/finance/treasurer) | [`Bill.paid`](/business/events/Bill.paid) | One-way (money): `send`, `do` | | [PayRun.pay](/business/nouns/pay-run/pay) | Pay funds an approved Pay Run: net pay to each employee’s bank on the pay date, taxes and deductions to the payroll provider. | [Treasurer](/agents/finance/treasurer) | [`PayRun.paid`](/business/events/PayRun.paid) | One-way (money): `send`, `do` | | [Account.payout](/business/nouns/account/payout) | Payout sends available cash from the payments balance to the owner’s bank and lists every Transaction the payout carries. | [Treasurer](/agents/finance/treasurer) | [`Account.paidOut`](/business/events/Account.paidOut) | One-way (money): `send`, `do` | | [Entry.post](/business/nouns/entry/post) | Post records a manual Entry pair that no Verb caused, once a second Role approves it. | [Finance Lead](/agents/finance/finance-lead) | [`Entry.posted`](/business/events/Entry.posted) | One-way: `send`, `do` | | [PayRun.prepare](/business/nouns/pay-run/prepare) | Prepare computes one pay period’s gross pay, withholding, deductions and employer taxes for each employee, and holds the Pay Run for approval. | [Payroll Specialist](/agents/people/payroll-specialist) | [`PayRun.prepared`](/business/events/PayRun.prepared) | Two-way: `try`, `send`, `do` | | [Template.promote](/business/nouns/template/promote) | Promote moves one Startup’s refinement into a Template, so every Startup that extends the Template inherits it. | [Agent](/business/nouns/agent) | [`Template.promoted`](/business/events/Template.promoted) | None. | | [StartupTemplate.promote](/business/nouns/startup-template/promote) | Promote moves one Startup’s refinement into a Startup Template, so every Startup that extends it inherits the refinement. | [Product Lead](/agents/product/product-lead) | [`StartupTemplate.promoted`](/business/events/StartupTemplate.promoted) | Two-way: `try`, `send`, `do` | | [Deal.propose](/business/nouns/deal/propose) | Propose sends a Deal’s buyer a Quote they accept to place an Order. | [Sales Lead](/agents/sales/sales-lead) | [`Deal.proposed`](/business/events/Deal.proposed) | One-way (money, customer): `send`, `do` | | [Tenant.provision](/business/nouns/tenant/provision) | Provision creates a Customer’s Tenant in a Startup’s App, holding that Customer’s records apart from every other. | [Integration Engineer](/agents/engineering/integration-engineer) | [`Tenant.provisioned`](/business/events/Tenant.provisioned) | None. | | [MemberDirectory.provision](/business/nouns/member-directory/provision) | Provision starts a Customer’s Member Directory pushing people and groups into its Tenant, with groups mapped to Roles. | [Security Engineer](/agents/engineering/security-engineer) | [`MemberDirectory.provisioned`](/business/events/MemberDirectory.provisioned) | Two-way: `try`, `send`, `do` | | [Offer.publish](/business/nouns/offer/publish) | Publish makes an Offer available for parties to accept. | [Product Lead](/agents/product/product-lead) | [`Offer.published`](/business/events/Offer.published) | None. | | [App.publish](/business/nouns/app/publish) | Publish releases an App to its Customers, so each Tenant runs its newest build. | [Engineering Lead](/agents/engineering/engineering-lead) | [`App.published`](/business/events/App.published) | None. | | [Site.publish](/business/nouns/site/publish) | Publish puts a Site’s current Pages live on its Domains, under its Brand. | [Designer](/agents/product/designer) | [`Site.published`](/business/events/Site.published) | None. | | [Content.publish](/business/nouns/content/publish) | Publish puts a Content draft live on its Site and every Interface, once it passes the Evals for its kind. | [Content Lead](/agents/marketing/content-lead) | [`Content.published`](/business/events/Content.published) | One-way (brand): `send`, `do` | | [Post.publish](/business/nouns/post/publish) | Publish sends a Post out through its Handle once every claim it states resolves to a live record. | [Content Lead](/agents/marketing/content-lead) | [`Post.published`](/business/events/Post.published) | One-way (brand): `send`, `do` | | [Review.publish](/business/nouns/review/publish) | Publish shows a Review on the Startup’s Pages with its rating counted, whatever the rating. | [Marketing Lead](/agents/marketing/marketing-lead) | [`Review.published`](/business/events/Review.published) | Two-way: `try`, `send`, `do` | | [Idea.pursue](/business/nouns/idea/pursue) | Pursue starts a Startup on an Idea as one variant of the Experiment that tests the Idea. | [Founder](/agents/founding/founder) | [`Idea.pursued`](/business/events/Idea.pursued) | None. | | [Lead.qualify](/business/nouns/lead/qualify) | Qualify confirms a Lead matches an Offer’s ICP and opens a Deal for it. | [Sales Engineer](/agents/sales/sales-engineer) | [`Lead.qualified`](/business/events/Lead.qualified) | None. | | [Metric.query](/business/nouns/metric/query) | Query reads Metrics or Events as a trend, funnel, retention curve, path or lifecycle, broken down by any property. | [Analyst](/agents/marketing/analyst) | [`Metric.queried`](/business/events/Metric.queried) | Two-way: `try`, `send`, `do` | | [Collection.query](/business/nouns/collection/query) | Query reads any Nouns the caller’s Permissions allow, by SQL or a Relationship path, across every System in one call. | [Analyst](/agents/marketing/analyst) | [`Collection.queried`](/business/events/Collection.queried) | Two-way: `try`, `send`, `do` | | [Limit.raise](/business/nouns/limit/raise) | Raise lifts a Limit after an Approval allows it, and the Action that waited on it proceeds. | [Founder](/agents/founding/founder) | [`Limit.raised`](/business/events/Limit.raised) | One-way (money): `send`, `do` | | [Problem.rank](/business/nouns/problem/rank) | Rank orders Problems by revenue at stake, Evidence grade and effort, so the next Project addresses the top one. | [Product Lead](/agents/product/product-lead) | [`Problem.ranked`](/business/events/Problem.ranked) | Two-way: `try`, `send`, `do` | | [Startup.read](/business/nouns/startup/read) | Read compiles a Startup’s records into one scoped room, such as a diligence room, with every number citing its Proof. | [Agent](/business/nouns/agent) | [`Startup.read`](/business/events/Startup.read) | Two-way: `try`, `send`, `do` | | [Period.recognize](/business/nouns/period/recognize) | Recognize moves the revenue a Period earned out of deferred revenue, by the Startup’s revenue-recognition Policy. | [Finance Lead](/agents/finance/finance-lead) | [`Period.recognized`](/business/events/Period.recognized) | Two-way: `try`, `send`, `do` | | [Transaction.reconcile](/business/nouns/transaction/reconcile) | Reconcile matches a Transaction on a payment rail to the ledger Entries it settles. | [Finance Lead](/agents/finance/finance-lead) | [`Transaction.reconciled`](/business/events/Transaction.reconciled) | Two-way: `try`, `send`, `do` | | [Human.recruit](/business/nouns/human/recruit) | Recruit invites a person to supply credentialed work to a Startup through its supply App. | [Supply Manager](/agents/operations/supply-manager) | [`Human.recruited`](/business/events/Human.recruited) | None. | | [Action.redirect](/business/nouns/action/redirect) | Redirect changes a pending Action’s inputs or target inside its delay window, before it runs. | [Operations Lead](/agents/operations/operations-lead) | [`Action.redirected`](/business/events/Action.redirected) | None. | | [Integration.refresh](/business/nouns/integration/refresh) | Refresh renews an Integration’s outside token before it expires; a refused refresh moves it to `needsReauth`. | [Integration Engineer](/agents/engineering/integration-engineer) | [`Integration.refreshed`](/business/events/Integration.refreshed) | Two-way: `try`, `send`, `do` | | [Order.refund](/business/nouns/order/refund) | Refund returns all or part of an Order’s payment to the Customer and posts the reversing Entries. | [Billing Specialist](/agents/finance/billing-specialist) | [`Order.refunded`](/business/events/Order.refunded) | One-way (money, customer): `send`, `do` | | [Invoice.refund](/business/nouns/invoice/refund) | Refund returns all or part of a paid Invoice to the Customer’s original payment method and posts the reversing Entries. | [Billing Specialist](/agents/finance/billing-specialist) | [`Invoice.refunded`](/business/events/Invoice.refunded) | One-way (money, customer): `send`, `do` | | [Approval.refuse](/business/nouns/approval/refuse) | Refuse declines an Approval, which sets the Action it holds to `refused` with the reason given. | [Founder](/agents/founding/founder) | [`Approval.refused`](/business/events/Approval.refused) | None. | | [Domain.register](/business/nouns/domain/register) | Register buys a hostname for a Startup and points it at the Startup’s address. | [Integration Engineer](/agents/engineering/integration-engineer) | [`Domain.registered`](/business/events/Domain.registered) | One-way (money): `send`, `do` | | [Company.register](/business/nouns/company/register) | Register applies for a sales tax, VAT or GST registration in one jurisdiction and records the grant as a Credential. | [Finance Lead](/agents/finance/finance-lead) | [`Company.registered`](/business/events/Company.registered) | One-way: `send`, `do` | | [Thing.relate](/business/nouns/thing/relate) | Relate links two Things by a Relationship their Nouns declare, readable from both ends at once. | [Data Engineer](/agents/engineering/data-engineer) | [`Thing.related`](/business/events/Thing.related) | Two-way: `try`, `send`, `do` | | [Domain.release](/business/nouns/domain/release) | Release lets a Domain’s registration or claim end, keeping its record, history and aliases. | [Legal Lead](/agents/legal/legal-lead) | [`Domain.released`](/business/events/Domain.released) | One-way (customer, brand): `send`, `do` | | [Human.release](/business/nouns/human/release) | Release frees a held amount for payout once its Dispute closes or its clearance period ends. | [Billing Specialist](/agents/finance/billing-specialist) | [`Human.released`](/business/events/Human.released) | Two-way: `try`, `send`, `do` | | [Human.remit](/business/nouns/human/remit) | Remit pays a supplying Human’s earned balance to their bank account through the Startup’s payment account. | [Supply Manager](/agents/operations/supply-manager) | [`Human.remitted`](/business/events/Human.remitted) | One-way (money): `send`, `do` | | [DNSRecord.remove](/business/nouns/dns-record/remove) | Remove stops a Startup-owned DNS Record from answering; its history stays and a revert restores it. | [Reliability Engineer](/agents/engineering/reliability-engineer) | [`DNSRecord.removed`](/business/events/DNSRecord.removed) | Two-way: `try`, `send`, `do` | | [Review.remove](/business/nouns/review/remove) | Remove takes a Review down for good when its author or its venue asks; the record is kept. | [Marketing Lead](/agents/marketing/marketing-lead) | [`Review.removed`](/business/events/Review.removed) | Two-way: `try`, `send`, `do` | | [Document.render](/business/nouns/document/render) | Render produces a file from a Document in the format the reader asks for. | [Agent](/business/nouns/agent) | [`Document.rendered`](/business/events/Document.rendered) | None. | | [Subscription.renew](/business/nouns/subscription/renew) | Renew starts a Subscription’s next period and bills it at the Offer Version the Customer accepted. | [Billing Specialist](/agents/finance/billing-specialist) | [`Subscription.renewed`](/business/events/Subscription.renewed) | Two-way: `try`, `send`, `do` | | [Domain.renew](/business/nouns/domain/renew) | Renew extends a Domain’s registration by whole years at its renewal price, paid by its owner of record. | [Treasurer](/agents/finance/treasurer) | [`Domain.renewed`](/business/events/Domain.renewed) | One-way (money): `send`, `do` | | [Issue.reopen](/business/nouns/issue/reopen) | Reopen returns a resolved Issue to its owning Role when the fix does not hold. | [Product Lead](/agents/product/product-lead) | [`Issue.reopened`](/business/events/Issue.reopened) | None. | | [Conversation.reopen](/business/nouns/conversation/reopen) | Reopen reverses a Conversation’s resolution when a reversal signal arrives within 7 days, and grades the resolution a failure. | [Customer Lead](/agents/customer/customer-lead) | [`Conversation.reopened`](/business/events/Conversation.reopened) | Two-way: `try`, `send`, `do` | | [Watch.replay](/business/nouns/watch/replay) | Replay redelivers a Watch’s Events from a chosen point, signed as they were the first time. | [Quality Lead](/agents/quality/quality-lead) | [`Watch.replayed`](/business/events/Watch.replayed) | None. | | Fund.report | Report sends each investor a quarterly capital account Statement and the Fund’s marks, computed from its Entries. | [Treasurer](/agents/finance/treasurer) | `Fund.reported` | One-way (brand): `send`, `do` | | [Tenant.requestSetup](/business/nouns/tenant/request-setup) | RequestSetup sends a Customer’s admin a link to connect their own sign-in, directory or verified domain to the Tenant. | [Security Engineer](/agents/engineering/security-engineer) | [`Tenant.setupRequested`](/business/events/Tenant.setupRequested) | Two-way: `try`, `send`, `do` | | [Issue.resolve](/business/nouns/issue/resolve) | Resolve closes an Issue with its fix recorded and tells every Customer who reported it. | [Product Lead](/agents/product/product-lead) | [`Issue.resolved`](/business/events/Issue.resolved) | None. | | [Incident.resolve](/business/nouns/incident/resolve) | Resolve closes an Incident once its Monitors pass, posts the resolution to the status page and opens the review Task. | [Reliability Engineer](/agents/engineering/reliability-engineer) | [`Incident.resolved`](/business/events/Incident.resolved) | Two-way: `try`, `send`, `do` | | [Thing.resolve](/business/nouns/thing/resolve) | Resolve finds the one Thing of a Noun that matches given properties, or creates it, and says which it did. | [Data Engineer](/agents/engineering/data-engineer) | [`Thing.resolved`](/business/events/Thing.resolved) | Two-way: `try`, `send`, `do` | | [Mailbox.rest](/business/nouns/mailbox/rest) | Rest pauses a Mailbox’s sending when a brake fires and resumes it when the reading clears. | [Customer Lead](/agents/customer/customer-lead) | [`Mailbox.rested`](/business/events/Mailbox.rested) | Two-way: `try`, `send`, `do` | | [Startup.resume](/business/nouns/startup/resume) | Resume returns a Dormant Startup to the Lifecycle state it held when it paused. | [Founder](/agents/founding/founder) | [`Startup.resumed`](/business/events/Startup.resumed) | None. | | [Enrollment.resume](/business/nouns/enrollment/resume) | Resume restarts a paused run at the step it stopped on and sets when that step fires. | [Prospector](/agents/sales/prospector) | [`Enrollment.resumed`](/business/events/Enrollment.resumed) | Two-way: `try`, `send`, `do` | | [Agent.resume](/business/nouns/agent/resume) | Resume restarts a paused Agent in every seat it holds, with its Memory, Mandates and Limits unchanged. | [Founder](/agents/founding/founder) | [`Agent.resumed`](/business/events/Agent.resumed) | Two-way: `try`, `send`, `do` | | [Noun.retire](/business/nouns/noun/retire) | Retire removes a published Noun from new Versions; its records, its history and every pinned Version keep serving. | [Product Lead](/agents/product/product-lead) | [`Noun.retired`](/business/events/Noun.retired) | One-way (customer): `send`, `do` | | [Verb.retire](/business/nouns/verb/retire) | Retire removes a published Verb from new Versions; callers pinned to earlier Versions keep calling it. | [Product Lead](/agents/product/product-lead) | [`Verb.retired`](/business/events/Verb.retired) | One-way (customer): `send`, `do` | | [Mailbox.retire](/business/nouns/mailbox/retire) | Retire stops a Mailbox for good and keeps its address, Messages and sending history. | [Customer Lead](/agents/customer/customer-lead) | [`Mailbox.retired`](/business/events/Mailbox.retired) | One-way: `send`, `do` | | [Voice.retire](/business/nouns/voice/retire) | Retire deletes a Voice’s trained copy at the upstream and refuses new speech in it, keeping the record and every File made. | [Privacy Officer](/agents/legal/privacy-officer) | [`Voice.retired`](/business/events/Voice.retired) | One-way (brand): `send`, `do` | | [Agent.retire](/business/nouns/agent/retire) | Retire removes an Agent from every seat in a Startup for good and keeps its Actions, Memory and Mailbox history on the record. | [People Lead](/agents/people/people-lead) | [`Agent.retired`](/business/events/Agent.retired) | One-way (customer): `send`, `do` | | [Action.retry](/business/nouns/action/retry) | Retry runs a failed Action again as a new Action linked to the one that failed. | [Reliability Engineer](/agents/engineering/reliability-engineer) | [`Action.retried`](/business/events/Action.retried) | None. | | [Change.revert](/business/nouns/change/revert) | Revert undoes a merged Change with a new Change and a superseding Decision, deleting nothing. | [Engineering Lead](/agents/engineering/engineering-lead) | [`Change.reverted`](/business/events/Change.reverted) | None. | | [Change.review](/business/nouns/change/review) | Review runs every Evaluator on a Change’s preview and records each verdict on the Change. | [Quality Lead](/agents/quality/quality-lead) | [`Change.reviewed`](/business/events/Change.reviewed) | None. | | [Role.review](/business/nouns/role/review) | Review checks one Role against its contract for a period and records a Role Review. | [Founder](/agents/founding/founder) | [`Role.reviewed`](/business/events/Role.reviewed) | Two-way: `try`, `send`, `do` | | [Mandate.revoke](/business/nouns/mandate/revoke) | Revoke ends a Mandate at once, so new Actions under it are refused and running ones finish. | [Security Engineer](/agents/engineering/security-engineer) | [`Mandate.revoked`](/business/events/Mandate.revoked) | None. | | [Secret.revoke](/business/nouns/secret/revoke) | Revoke ends a Secret so no call fills it again; the record and its history stay. | [Security Engineer](/agents/engineering/security-engineer) | [`Secret.revoked`](/business/events/Secret.revoked) | One-way (customer): `send`, `do` | | [APIKey.revoke](/business/nouns/api-key/revoke) | Revoke stops an API Key at once: its next call fails with 401, and the record and its history stay. | [Agent](/business/nouns/agent) | [`APIKey.revoked`](/business/events/APIKey.revoked) | Two-way: `try`, `send`, `do` | | [APIKey.roll](/business/nouns/api-key/roll) | Roll issues a replacement API Key with the same scope and keeps the old one working until a set time. | [Agent](/business/nouns/agent) | [`APIKey.rolled`](/business/events/APIKey.rolled) | Two-way: `try`, `send`, `do` | | [Secret.rotate](/business/nouns/secret/rotate) | Rotate replaces a Secret’s value, and calls already running finish on the old one. | [Security Engineer](/agents/engineering/security-engineer) | [`Secret.rotated`](/business/events/Secret.rotated) | Two-way: `try`, `send`, `do` | | [Issue.schedule](/business/nouns/issue/schedule) | Schedule commits an Issue to a week of work and records each scope change after the week starts. | [Product Lead](/agents/product/product-lead) | [`Issue.scheduled`](/business/events/Issue.scheduled) | Two-way: `try`, `send`, `do` | | [Dashboard.schedule](/business/nouns/dashboard/schedule) | Schedule sends a Dashboard on a cadence to a Mailbox, a Channel or an Agent’s context, rendered for each. | [Analyst](/agents/marketing/analyst) | [`Dashboard.scheduled`](/business/events/Dashboard.scheduled) | Two-way: `try`, `send`, `do` | | [Message.schedule](/business/nouns/message/schedule) | Schedule holds a Message until a set time and sends it then, unless it is canceled first. | [Marketing Lead](/agents/marketing/marketing-lead) | [`Message.scheduled`](/business/events/Message.scheduled) | Two-way: `try`, `send`, `do` | | [Post.schedule](/business/nouns/post/schedule) | Schedule puts a drafted Post on its Handle’s calendar for a set time. | [Content Lead](/agents/marketing/content-lead) | [`Post.scheduled`](/business/events/Post.scheduled) | Two-way: `try`, `send`, `do` | | [Candidate.screen](/business/nouns/candidate/screen) | Screen asks a Candidate only what the Opening’s Hypothesis still lacks, in writing, and grades each answer as Evidence. | [Recruiter](/agents/people/recruiter) | [`Candidate.screened`](/business/events/Candidate.screened) | None. | | [Party.screen](/business/nouns/party/screen) | Screen checks a Party against official registers and restricted-party lists and keeps the result as a Screening. | [Risk Analyst](/agents/operations/risk-analyst) | [`Party.screened`](/business/events/Party.screened) | Two-way: `try`, `send`, `do` | | [Order.screen](/business/nouns/order/screen) | Screen scores an Order’s payment before it is charged and allows, authenticates, holds or blocks it by the Startup’s risk Policy. | [Risk Analyst](/agents/operations/risk-analyst) | [`Order.screened`](/business/events/Order.screened) | Two-way: `try`, `send`, `do` | | [Domain.search](/business/nouns/domain/search) | Search lists candidate names with availability, first-year price, renewal price and the rules of each extension. | [Engineering Lead](/agents/engineering/engineering-lead) | [`Domain.searched`](/business/events/Domain.searched) | Two-way: `try`, `send`, `do` | | [Quote.send](/business/nouns/quote/send) | Send presents a drafted Quote to its buyer and freezes its lines, total and payment terms. | [Sales Engineer](/agents/sales/sales-engineer) | [`Quote.sent`](/business/events/Quote.sent) | One-way (customer): `send`, `do` | | [DNSRecord.set](/business/nouns/dns-record/set) | Set adds or changes a Startup-owned DNS Record through a Change, previewed against what the Domain answers today. | [Reliability Engineer](/agents/engineering/reliability-engineer) | [`DNSRecord.set`](/business/events/DNSRecord.set) | Two-way: `try`, `send`, `do` | | [Entry.settle](/business/nouns/entry/settle) | Settle nets a Period’s intercompany Entries between two Companies into one transfer through Stripe and reconciles both sides. | [Treasurer](/agents/finance/treasurer) | [`Entry.settled`](/business/events/Entry.settled) | One-way (money): `send`, `do` | | [Thing.share](/business/nouns/thing/share) | Share grants a person, a Role or a guest Verbs on one record and everything it contains. | [Security Engineer](/agents/engineering/security-engineer) | [`Thing.shared`](/business/events/Thing.shared) | Two-way: `try`, `send`, `do` | | [Mandate.spend](/business/nouns/mandate/spend) | Spend pays an outside party for a Startup with a single-use card, within a Mandate and its Limit. | [Treasurer](/agents/finance/treasurer) | [`Mandate.spent`](/business/events/Mandate.spent) | One-way (money): `send`, `do` | | [Role.staff](/business/nouns/role/staff) | Staff fills a Role with a Worker, human or agent, who then performs the Role’s Verbs under its Permissions. | [People Lead](/agents/people/people-lead) | [`Role.staffed`](/business/events/Role.staffed) | None. | | [Experiment.start](/business/nouns/experiment/start) | Start opens an Experiment, splits traffic across its variants, and begins measuring its primary and guardrail Metrics. | [Strategist](/agents/founding/strategist) | [`Experiment.started`](/business/events/Experiment.started) | None. | | [Order.start](/business/nouns/order/start) | Start checks a Service Order’s inputs against its brief, then moves it from intake to working and starts its deadline. | [Delivery Manager](/agents/operations/delivery-manager) | [`Order.started`](/business/events/Order.started) | Two-way: `try`, `send`, `do` | | [Secret.store](/business/nouns/secret/store) | Store writes a Secret’s value for one environment; the value is never returned by any Interface. | [Security Engineer](/agents/engineering/security-engineer) | [`Secret.stored`](/business/events/Secret.stored) | Two-way: `try`, `send`, `do` | | [Company.submit](/business/nouns/company/submit) | Submit files one tax return for a jurisdiction and its Periods, pays the tax due, and keeps the return as a Document. | [Finance Lead](/agents/finance/finance-lead) | [`Company.submitted`](/business/events/Company.submitted) | One-way (money): `send`, `do` | | [Decision.supersede](/business/nouns/decision/supersede) | Supersede replaces a Decision with a newer one, keeping both on record with the reason for the change. | [Strategist](/agents/founding/strategist) | [`Decision.superseded`](/business/events/Decision.superseded) | None. | | [Quote.supersede](/business/nouns/quote/supersede) | Supersede replaces a sent Quote with a newer one on the same Deal; only the newest Quote can be accepted. | [Sales Engineer](/agents/sales/sales-engineer) | [`Quote.superseded`](/business/events/Quote.superseded) | Two-way: `try`, `send`, `do` | | [Contact.suppress](/business/nouns/contact/suppress) | Suppress records a Suppression for a Contact’s address, which every Startup honors forever. | [Prospector](/agents/sales/prospector) | [`Contact.suppressed`](/business/events/Contact.suppressed) | None. | | [Human.suspend](/business/nouns/human/suspend) | Suspend stops a supplying Human from taking new Tasks while a Credential lapses or a dispute is open. | [Supply Manager](/agents/operations/supply-manager) | [`Human.suspended`](/business/events/Human.suspended) | None. | | [Account.sweep](/business/nouns/account/sweep) | Sweep moves cash between two cash Accounts of the same owner, once or on a standing rule, within the Treasurer’s Limit. | [Treasurer](/agents/finance/treasurer) | [`Account.swept`](/business/events/Account.swept) | Two-way: `try`, `send`, `do` | | [Integration.sync](/business/nouns/integration/sync) | Sync exchanges records between a System and its connector, and the declared leader wins every conflict. | [Reliability Engineer](/agents/engineering/reliability-engineer) | [`Integration.synced`](/business/events/Integration.synced) | None. | | [Hypothesis.test](/business/nouns/hypothesis/test) | Test binds a Hypothesis to the Experiment that decides it and moves the Hypothesis to testing. | [Strategist](/agents/founding/strategist) | [`Hypothesis.tested`](/business/events/Hypothesis.tested) | None. | | [Domain.transfer](/business/nouns/domain/transfer) | Transfer moves a Domain’s registration to another holder or registrar, with its records intact. | [Legal Lead](/agents/legal/legal-lead) | [`Domain.transferred`](/business/events/Domain.transferred) | One-way (customer): `send`, `do` | | [Share.transfer](/business/nouns/share/transfer) | Transfer moves Shares from one Holder to another under a signed Agreement, within the Company’s transfer restrictions. | [Legal Lead](/agents/legal/legal-lead) | [`Share.transferred`](/business/events/Share.transferred) | One-way: `send`, `do` | | [Risk.treat](/business/nouns/risk/treat) | Treat links a Risk to the Controls that lower it and records the score it should reach. | [Risk Analyst](/agents/operations/risk-analyst) | [`Risk.treated`](/business/events/Risk.treated) | Two-way: `try`, `send`, `do` | | [Issue.triage](/business/nouns/issue/triage) | Triage sets an Issue’s severity and owning Role from its content and the Customer it affects. | [Product Lead](/agents/product/product-lead) | [`Issue.triaged`](/business/events/Issue.triaged) | None. | | [Thing.unrelate](/business/nouns/thing/unrelate) | Unrelate ends a Relationship between two Things; the link stays in history and reads back at any earlier moment. | [Data Engineer](/agents/engineering/data-engineer) | [`Thing.unrelated`](/business/events/Thing.unrelated) | Two-way: `try`, `send`, `do` | | [Template.upgrade](/business/nouns/template/upgrade) | Upgrade moves a Startup to a newer Version of a Template it extends, through a Change it can review. | [Agent](/business/nouns/agent) | [`Template.upgraded`](/business/events/Template.upgraded) | None. | | [StartupTemplate.upgrade](/business/nouns/startup-template/upgrade) | Upgrade moves a Startup to a newer Version of a Startup Template it extends, through a Change it can review. | [Engineering Lead](/agents/engineering/engineering-lead) | [`StartupTemplate.upgraded`](/business/events/StartupTemplate.upgraded) | Two-way: `try`, `send`, `do` | | [Credential.verify](/business/nouns/credential/verify) | Verify confirms a Credential with the authority that issued it and records when it expires. | [Supply Manager](/agents/operations/supply-manager) | [`Credential.verified`](/business/events/Credential.verified) | None. | | [Domain.verify](/business/nouns/domain/verify) | Verify checks a Domain’s DNS, ownership and certificate again and records each result, with the fix for any failure. | [Reliability Engineer](/agents/engineering/reliability-engineer) | [`Domain.verified`](/business/events/Domain.verified) | Two-way: `try`, `send`, `do` | | [Invoice.void](/business/nouns/invoice/void) | Void cancels an unpaid Invoice, keeps it on record, and posts the reversing Entries. | [Billing Specialist](/agents/finance/billing-specialist) | [`Invoice.voided`](/business/events/Invoice.voided) | One-way (money, customer): `send`, `do` | | [CreditGrant.void](/business/nouns/credit-grant/void) | Void ends a promotional Credit Grant early and forfeits its remaining balance, keeping the record. | [Billing Specialist](/agents/finance/billing-specialist) | [`CreditGrant.voided`](/business/events/CreditGrant.voided) | One-way (customer): `send`, `do` | | [PayRun.void](/business/nouns/pay-run/void) | Void sets aside a prepared Pay Run that is wrong, so a corrected one can be prepared; the record stays. | [Payroll Specialist](/agents/people/payroll-specialist) | [`PayRun.voided`](/business/events/PayRun.voided) | Two-way: `try`, `send`, `do` | | [Mailbox.warm](/business/nouns/mailbox/warm) | Warm ramps a new Mailbox from a few sends a day to its cap over two to four weeks. | [Customer Lead](/agents/customer/customer-lead) | [`Mailbox.warmed`](/business/events/Mailbox.warmed) | Two-way: `try`, `send`, `do` | | [Metric.watch](/business/nouns/metric/watch) | Watch alerts the owner of a Metric when it crosses a threshold, by a Task or a Message. | [Analyst](/agents/marketing/analyst) | [`Metric.watched`](/business/events/Metric.watched) | Two-way: `try`, `send`, `do` | | [Deal.win](/business/nouns/deal/win) | Win closes a Deal as won, which places its Order and makes the buyer a Customer. | [Sales Lead](/agents/sales/sales-lead) | [`Deal.won`](/business/events/Deal.won) | None. | | [Offer.withdraw](/business/nouns/offer/withdraw) | Withdraw closes a published Offer to new Customers and leaves every existing Order and Subscription in force. | [Product Lead](/agents/product/product-lead) | [`Offer.withdrawn`](/business/events/Offer.withdrawn) | None. | | [Post.withdraw](/business/nouns/post/withdraw) | Withdraw takes a published Post down from its venue and keeps the record, its reach and its replies. | [Content Lead](/agents/marketing/content-lead) | [`Post.withdrawn`](/business/events/Post.withdrawn) | One-way: `send`, `do` | | [Review.withhold](/business/nouns/review/withhold) | Withhold keeps a Review off display for one of five reasons, none of them its rating or its tone. | [Marketing Lead](/agents/marketing/marketing-lead) | [`Review.withheld`](/business/events/Review.withheld) | Two-way: `try`, `send`, `do` | | [Agent.create](/business/nouns/agent/create) | Creates an Agent. Inherited from [Noun](/business/nouns/noun). | None. | `Agent.created` | Two-way: `try`, `send`, `do` | | [Agent.get](/business/nouns/agent/get) | Returns one Agent by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Agent.list](/business/nouns/agent/list) | Returns Agents, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Agent.update](/business/nouns/agent/update) | Changes the given properties of an Agent. Inherited from [Noun](/business/nouns/noun). | None. | `Agent.updated` | Two-way: `try`, `send`, `do` | | [Agent.delete](/business/nouns/agent/delete) | Deletes an Agent; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Agent.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Agent.create` | Yes | Yes | Yes | No | | `Agent.get` | Yes | Yes | Yes | Yes | | `Agent.list` | Yes | Yes | Yes | Yes | | `Agent.update` | Yes | Yes | Yes | No | | `Agent.delete` | Yes | Yes | Yes | No | | `Agent.mint` | Yes | Yes | Yes | No | | `Agent.pause` | Yes | Yes | Yes | No | | `Agent.resume` | Yes | Yes | Yes | No | | `Agent.retire` | Yes | No | No | No | ## Call it **Ask** ```text Mint the latest agent with a tenant and a product. ``` **API** ```bash curl -X POST https://api.sb/patentpad.com/agents/mint \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"tenant":"tenant_1","product":"product_1"}' ``` ```json { "api": "https://api.sb/patentpad.com", "agent": { "$id": "https://api.sb/patentpad.com/agents/agent_1", "$type": "Agent", "instructions": "Example instructions", "model": "Example model", "status": "standby" }, "action": { "$id": "https://api.sb/patentpad.com/actions/action_1", "operation": "Agent.mint", "status": "done" }, "links": { "self": "https://api.sb/patentpad.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const agent = await $.Agent.mint({ tenant: 'tenant_1', product: 'product_1' }) ``` **CLI** ```bash npx startup-builder do Agent.mint --json '{"tenant":"tenant_1","product":"product_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Agent.mint({ tenant: 'tenant_1', product: 'product_1' })" } } ``` ## Example A support Agent fills the [Customer Lead](/agents/customer/customer-lead) Role at a tutoring marketplace. Its `instructions` say to answer from the help center and hand billing questions to a [Human](/business/nouns/human); its `tools` read tickets and post replies. # mint URL: /business/nouns/agent/mint · Id: `verb:Agent.mint` · Call: `await $.Agent.mint({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Mint creates an Agent in a Customer’s Tenant from an Agent Product the Customer bought. Mint creates an [Agent](/business/nouns/agent) in a [Customer](/business/nouns/customer)’s [Tenant](/business/nouns/tenant) from an Agent [Product](/business/nouns/product) the Customer bought. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `tenant` | [Tenant](/business/nouns/tenant) | Yes | The Customer’s Tenant. | | `product` | [Product](/business/nouns/product) | Yes | The Agent Product. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `agent` | [Agent](/business/nouns/agent) | Yes | The Customer’s own Agent. | ## Effects - Emits [`Agent.minted`](/business/events/Agent.minted). - Performed by the [People Lead](/agents/people/people-lead). - Bounds the Agent by the Customer’s Entitlements and their Limits. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The operation is part of an Offer the caller has not accepted or paid for. | [`payment-required`](/code/api/errors/payment-required) | Accept the Offer named in the response, then retry the call. | [Offer.accept](/business/nouns/offer/accept) | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Agent.mint](/business/nouns/agent/mint) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Mint the latest agent with a tenant and a product. ``` **API** ```bash curl -X POST https://api.sb/patentpad.com/agents/mint \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"tenant":"tenant_1","product":"product_1"}' ``` ```json { "api": "https://api.sb/patentpad.com", "agent": { "$id": "https://api.sb/patentpad.com/agents/agent_1", "$type": "Agent", "instructions": "Example instructions", "model": "Example model", "status": "standby" }, "action": { "$id": "https://api.sb/patentpad.com/actions/action_1", "operation": "Agent.mint", "status": "done" }, "links": { "self": "https://api.sb/patentpad.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const agent = await $.Agent.mint({ tenant: 'tenant_1', product: 'product_1' }) ``` **CLI** ```bash npx startup-builder do Agent.mint --json '{"tenant":"tenant_1","product":"product_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Agent.mint({ tenant: 'tenant_1', product: 'product_1' })" } } ``` # pause URL: /business/nouns/agent/pause · Id: `verb:Agent.pause` · Call: `await $.Agent.pause({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Pause stops one Agent, every Agent on a Team, or every customer-facing Agent from starting new Actions in a Startup. Pause stops one [Agent](/business/nouns/agent), every Agent on a [Team](/business/nouns/team), or every customer-facing Agent from starting new [Actions](/business/nouns/action) in a [Startup](/business/nouns/startup). ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `agents` | list of [Agent](/business/nouns/agent) | No | The Agents to pause. Name one of `agents`, `team` or `customerFacing`. | | `team` | [Team](/business/nouns/team) | No | Pause every Agent seated on this Team. | | `customerFacing` | `boolean` | No | True pauses every Agent seated in a Role that answers a customer Channel. | | `reason` | `text` | Yes | Why the Agents stop, shown to every watcher. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `agents` | list of [Agent](/business/nouns/agent) | Yes | Every Agent it paused; each emits its own `Agent.paused`. | ## Effects - Emits [`Agent.paused`](/business/events/Agent.paused). - Performed by the [Founder](/agents/founding/founder). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Holds every pending Action the Agent started; running Actions finish. - Keeps new Tasks in each seat’s queue, and sends each customer who writes a holding reply from the Role address. - Leaves Memory, Mandates and Limits untouched, so resume picks up where it stopped. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Agent.pause](/business/nouns/agent/pause) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Pause the latest agent. ``` **API** ```bash curl -X POST https://api.sb/ledgerlark.com/agents/pause \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"agents":["agent_1"],"reason":"Example reason"}' ``` ```json { "api": "https://api.sb/ledgerlark.com", "agents": [ { "$id": "https://api.sb/ledgerlark.com/agents/agent_1", "$type": "Agent", "instructions": "Example instructions", "model": "Example model", "status": "standby" } ], "action": { "$id": "https://api.sb/ledgerlark.com/actions/action_1", "operation": "Agent.pause", "status": "done" }, "links": { "self": "https://api.sb/ledgerlark.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const agents = await $.Agent.pause({ agents: ['agent_1'], reason: 'Example reason' }) ``` **CLI** ```bash npx startup-builder do Agent.pause --json '{"agents":["agent_1"],"reason":"Example reason"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Agent.pause({ agents: ['agent_1'], reason: 'Example reason' })" } } ``` Guides that call it: [Pause every agent that talks to customers](/agents/pause-customer-facing-agents). # resume URL: /business/nouns/agent/resume · Id: `verb:Agent.resume` · Call: `await $.Agent.resume({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Resume restarts a paused Agent in every seat it holds, with its Memory, Mandates and Limits unchanged. Resume restarts a paused [Agent](/business/nouns/agent) in every seat it holds, with its [Memory](/business/nouns/memory), [Mandates](/business/nouns/mandate) and [Limits](/business/nouns/limit) unchanged. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `agent` | [Agent](/business/nouns/agent) | Yes | The paused Agent. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `agent` | [Agent](/business/nouns/agent) | Yes | The working Agent. | ## Effects - Emits [`Agent.resumed`](/business/events/Agent.resumed). - Performed by the [Founder](/agents/founding/founder). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Releases held Actions into what remains of their delay windows, and works the queued Tasks oldest first. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Agent.resume](/business/nouns/agent/resume) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Resume the latest agent. ``` **API** ```bash curl -X POST https://api.sb/tutorloop.com/agents/agent_1/resume \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/tutorloop.com", "agent": { "$id": "https://api.sb/tutorloop.com/agents/agent_1", "$type": "Agent", "instructions": "Example instructions", "model": "Example model", "status": "standby" }, "action": { "$id": "https://api.sb/tutorloop.com/actions/action_1", "operation": "Agent.resume", "status": "done" }, "links": { "self": "https://api.sb/tutorloop.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const agent = await $.Agent.resume({ agent: 'agent_1' }) ``` **CLI** ```bash npx startup-builder do Agent.resume --json '{"agent":"agent_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Agent.resume({ agent: 'agent_1' })" } } ``` # retire URL: /business/nouns/agent/retire · Id: `verb:Agent.retire` · Call: `await $.Agent.retire({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Retire removes an Agent from every seat in a Startup for good and keeps its Actions, Memory and Mailbox history on the record. Retire removes an [Agent](/business/nouns/agent) from every seat in a [Startup](/business/nouns/startup) for good and keeps its [Actions](/business/nouns/action), [Memory](/business/nouns/memory) and [Mailbox](/business/nouns/mailbox) history on the record. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `agent` | [Agent](/business/nouns/agent) | Yes | The Agent to retire. | | `reason` | `text` | Yes | Why it leaves. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `agent` | [Agent](/business/nouns/agent) | Yes | The retired Agent. | ## Effects - Emits [`Agent.retired`](/business/events/Agent.retired). - Performed by the [People Lead](/agents/people/people-lead). - One-way (customer): it waits out its delay window, and runs in the `send` and `do` modes. - Vacates every Role the Agent held, so each seat’s Tasks route to the Role it escalates to. - Ends its Mandates and Permissions in this Startup. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Agent.retire](/business/nouns/agent/retire) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Medium: one-way, bounded (customer) | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | 1 business hour, in which a watcher can pause, redirect or cancel it; then it runs. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Retire the latest agent. ``` **API** ```bash curl -X POST https://api.sb/quietcopy.com/agents/agent_1/retire \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"reason":"Example reason"}' ``` ```json { "api": "https://api.sb/quietcopy.com", "agent": { "$id": "https://api.sb/quietcopy.com/agents/agent_1", "$type": "Agent", "instructions": "Example instructions", "model": "Example model", "status": "retired" }, "action": { "$id": "https://api.sb/quietcopy.com/actions/action_1", "operation": "Agent.retire", "status": "done" }, "links": { "self": "https://api.sb/quietcopy.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const agent = await $.Agent.retire({ agent: 'agent_1', reason: 'Example reason' }) ``` **CLI** ```bash npx startup-builder do Agent.retire --json '{"agent":"agent_1","reason":"Example reason"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Agent.retire({ agent: 'agent_1', reason: 'Example reason' })" } } ``` # Agreement URL: /business/nouns/agreement · Id: `noun:agreement` > An Agreement is a contract between two or more Parties, with its term, liability, and economics, that travels with the Startup. An Agreement is a contract between two or more [Parties](/business/nouns/party), with its term, liability, and economics, that travels with the [Startup](/business/nouns/startup). The holding [Company](/business/nouns/company) signs it. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `term` | `text` | No | How long it runs and how it ends. | | `signedAt` | `datetime` | No | When the last Party signed. | | `terminatedAt` | `datetime` | No | When it ended under its term; it stays on record. | | `payoutSchedule` | `string` | No | For a Supplier’s Agreement: how often the released earned balance pays out. | | `clearanceDays` | `integer` | No | For a Supplier’s Agreement: days an Order’s earnings wait after confirmation before they can pay out. | | `status` | `string` | Yes | One of `draft`, `signed` or `terminated`. | ## Object ```json { "$id": "https://api.sb/quietcopy.com/agreements/agreement_1", "$type": "Agreement", "term": "Example term", "signedAt": "2026-10-22T12:00:00Z", "terminatedAt": "2026-10-22T12:00:00Z", "payoutSchedule": "daily", "clearanceDays": 1, "status": "draft" } ``` ## Relationships - An Agreement **binds** many [Parties](/business/nouns/party): the [Parties](/business/nouns/party) the Agreement holds to its terms, each from the moment it signs. `binds`, inverse [`boundBy`](/business/nouns/party#rel-bound-by). - An Agreement **covers** many [Startups](/business/nouns/startup): the Agreements a [Startup](/business/nouns/startup) operates under travel with it when it graduates or sells. `covers`, inverse [`operatesUnder`](/business/nouns/startup#rel-operates-under). ## Lifecycle | State | Meaning | Moves to | | --- | --- | --- | | `draft` (first) | Its terms are written, and not every Party has signed. | `signed` by [Agreement.sign](/business/nouns/agreement/sign) | | `signed` | Every Party signed, and it binds them under its term. | `terminated` by [Agreement.terminate](/business/nouns/agreement/terminate) | | `terminated` | Ended under its own term, with the reason and date recorded and the signed copy kept. | None: it ends here. | ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Agreement.sign](/business/nouns/agreement/sign) | Sign executes an Agreement for one Party and records the signature, the signer and the time. | [Founder](/agents/founding/founder) | [`Agreement.signed`](/business/events/Agreement.signed) | One-way (money): `send`, `do` | | [Agreement.terminate](/business/nouns/agreement/terminate) | Terminate ends an Agreement under its own term, records the reason and the date, and keeps the signed record. | [Legal Lead](/agents/legal/legal-lead) | [`Agreement.terminated`](/business/events/Agreement.terminated) | One-way (money, customer): `send`, `do` | | [Agreement.create](/business/nouns/agreement/create) | Creates an Agreement. Inherited from [Noun](/business/nouns/noun). | None. | `Agreement.created` | Two-way: `try`, `send`, `do` | | [Agreement.get](/business/nouns/agreement/get) | Returns one Agreement by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Agreement.list](/business/nouns/agreement/list) | Returns Agreements, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Agreement.update](/business/nouns/agreement/update) | Changes the given properties of an Agreement. Inherited from [Noun](/business/nouns/noun). | None. | `Agreement.updated` | Two-way: `try`, `send`, `do` | An Agreement is never deleted: it ends by [Agreement.terminate](/business/nouns/agreement/terminate), and its records stay. ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Agreement.create` | Yes | Yes | Yes | No | | `Agreement.get` | Yes | Yes | Yes | Yes | | `Agreement.list` | Yes | Yes | Yes | Yes | | `Agreement.update` | Yes | Yes | Yes | No | | `Agreement.sign` | Yes | No | No | No | | `Agreement.terminate` | Yes | No | No | No | ## Call it **Ask** ```text Sign the latest agreement. ``` **API** ```bash curl -X POST https://api.sb/shiftnote.app/agreements/agreement_1/sign \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/shiftnote.app", "agreement": { "$id": "https://api.sb/shiftnote.app/agreements/agreement_1", "$type": "Agreement", "status": "signed" }, "action": { "$id": "https://api.sb/shiftnote.app/actions/action_1", "operation": "Agreement.sign", "status": "done" }, "links": { "self": "https://api.sb/shiftnote.app/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const agreement = await $.Agreement.sign({ agreement: 'agreement_1' }) ``` **CLI** ```bash npx startup-builder do Agreement.sign --json '{"agreement":"agreement_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Agreement.sign({ agreement: 'agreement_1' })" } } ``` ## Example A practice-management Startup signs an Agreement with a court-filings API: a three-year `term`, liability capped at annual fees, and 20% of referred first-year revenue. When the Startup sells, the Agreement moves with it. # sign URL: /business/nouns/agreement/sign · Id: `verb:Agreement.sign` · Call: `await $.Agreement.sign({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Sign executes an Agreement for one Party and records the signature, the signer and the time. Sign executes an [Agreement](/business/nouns/agreement) for one party and records the signature, the signer and the time. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `agreement` | [Agreement](/business/nouns/agreement) | Yes | The Agreement to sign. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `agreement` | [Agreement](/business/nouns/agreement) | Yes | The Agreement, in force once every party signs. | ## Effects - Emits [`Agreement.signed`](/business/events/Agreement.signed). - Performed by the [Founder](/agents/founding/founder). - One-way (money): it waits out its delay window, and runs in the `send` and `do` modes. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Agreement.sign](/business/nouns/agreement/sign) | | The record is not in a state that allows this Verb, so the call is refused. | [`refused`](/code/api/errors/refused) | Read the record, run the Verb that moves it to an allowed state, then retry. | [Agreement.sign](/business/nouns/agreement/sign) | ## When it waits | Gate | Default | | --- | --- | | Decision class | High: one-way, broad (money) | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | 1 business day, in which a watcher can pause, redirect or cancel it; then it runs. | | Limit | The spend [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) or [Mandate](/business/nouns/mandate) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Sign the latest agreement. ``` **API** ```bash curl -X POST https://api.sb/shiftnote.app/agreements/agreement_1/sign \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/shiftnote.app", "agreement": { "$id": "https://api.sb/shiftnote.app/agreements/agreement_1", "$type": "Agreement", "status": "signed" }, "action": { "$id": "https://api.sb/shiftnote.app/actions/action_1", "operation": "Agreement.sign", "status": "done" }, "links": { "self": "https://api.sb/shiftnote.app/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const agreement = await $.Agreement.sign({ agreement: 'agreement_1' }) ``` **CLI** ```bash npx startup-builder do Agreement.sign --json '{"agreement":"agreement_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Agreement.sign({ agreement: 'agreement_1' })" } } ``` # terminate URL: /business/nouns/agreement/terminate · Id: `verb:Agreement.terminate` · Call: `await $.Agreement.terminate({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Terminate ends an Agreement under its own term, records the reason and the date, and keeps the signed record. Terminate ends an [Agreement](/business/nouns/agreement) under its own term, records the reason and the date, and keeps the signed record. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `agreement` | [Agreement](/business/nouns/agreement) | Yes | The Agreement in force. | | `reason` | `text` | Yes | The term it ends under and why. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `agreement` | [Agreement](/business/nouns/agreement) | Yes | The terminated Agreement, kept forever. | ## Effects - Emits [`Agreement.terminated`](/business/events/Agreement.terminated). - Performed by the [Legal Lead](/agents/legal/legal-lead). - One-way (money, customer): it waits out its delay window, and runs in the `send` and `do` modes. - Notifies every bound Party. - Ends the Entitlements and recurring charges that depend on it. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Agreement.terminate](/business/nouns/agreement/terminate) | | The record changed since it was read, so the write would overwrite a newer version. | [`conflict`](/code/api/errors/conflict) | Read the record again, then retry the write against its current state. | [Agreement.terminate](/business/nouns/agreement/terminate) | | The record is not in a state that allows this Verb, so the call is refused. | [`refused`](/code/api/errors/refused) | Read the record, run the Verb that moves it to an allowed state, then retry. | [Agreement.terminate](/business/nouns/agreement/terminate) | ## When it waits | Gate | Default | | --- | --- | | Decision class | High: one-way, broad (money, customer) | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | 1 business day, in which a watcher can pause, redirect or cancel it; then it runs. | | Limit | The spend [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) or [Mandate](/business/nouns/mandate) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Terminate the latest agreement. ``` **API** ```bash curl -X POST https://api.sb/shiftnote.app/agreements/agreement_1/terminate \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"reason":"Example reason"}' ``` ```json { "api": "https://api.sb/shiftnote.app", "agreement": { "$id": "https://api.sb/shiftnote.app/agreements/agreement_1", "$type": "Agreement", "status": "terminated" }, "action": { "$id": "https://api.sb/shiftnote.app/actions/action_1", "operation": "Agreement.terminate", "status": "done" }, "links": { "self": "https://api.sb/shiftnote.app/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const agreement = await $.Agreement.terminate({ agreement: 'agreement_1', reason: 'Example reason' }) ``` **CLI** ```bash npx startup-builder do Agreement.terminate --json '{"agreement":"agreement_1","reason":"Example reason"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Agreement.terminate({ agreement: 'agreement_1', reason: 'Example reason' })" } } ``` # API Key URL: /business/nouns/api-key · Id: `noun:api-key` > An API Key is a secret a Startup issues to one Customer, which signs that Customer’s calls to its API, SDK, CLI and MCP server. An API Key is a secret a [Startup](/business/nouns/startup) issues to one [Customer](/business/nouns/customer), which signs that Customer’s calls to its API, SDK, CLI and MCP server. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `name` | `string` | Yes | What the Customer calls it, so a list of keys reads by purpose. | | `environment` | `string` | Yes | One of `test` or `live`: a `test` key reaches test records and moves no money. | | `verbs` | list of [Verb](/business/nouns/verb) | No | The Verbs it may call. Unset: every Verb the Customer’s Entitlements grant. | | `prefix` | `string` | No | The first characters of the secret, shown in place of it everywhere after issue. | | `lastUsedAt` | `datetime` | No | When it last signed a call. | | `expiresAt` | `datetime` | No | When it stops working on its own. Unset: it works until rolled or revoked. | | `revokedAt` | `datetime` | No | When it was revoked. A revoked key fails its next call. | ## Object ```json { "$id": "https://api.sb/petpantry.shop/api-keys/api_key_1", "$type": "APIKey", "name": "Nightly sync", "environment": "test", "verbs": [ "verb_1" ], "prefix": "sk_live_4f2a", "lastUsedAt": "2026-10-22T12:00:00Z", "expiresAt": "2026-10-22T12:00:00Z", "revokedAt": "2026-10-22T12:00:00Z" } ``` ## Relationships - An API Key **reaches** one [Tenant](/business/nouns/tenant): every call it signs reads and writes only that [Customer](/business/nouns/customer)’s records. `reaches`, inverse [`apiKeys`](/business/nouns/tenant#rel-api-keys). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [APIKey.issue](/business/nouns/api-key/issue) | Issue creates an API Key for one Customer and returns its secret once; afterwards only the prefix shows. | [Agent](/business/nouns/agent) | [`APIKey.issued`](/business/events/APIKey.issued) | Two-way: `try`, `send`, `do` | | [APIKey.revoke](/business/nouns/api-key/revoke) | Revoke stops an API Key at once: its next call fails with 401, and the record and its history stay. | [Agent](/business/nouns/agent) | [`APIKey.revoked`](/business/events/APIKey.revoked) | Two-way: `try`, `send`, `do` | | [APIKey.roll](/business/nouns/api-key/roll) | Roll issues a replacement API Key with the same scope and keeps the old one working until a set time. | [Agent](/business/nouns/agent) | [`APIKey.rolled`](/business/events/APIKey.rolled) | Two-way: `try`, `send`, `do` | | [APIKey.get](/business/nouns/api-key/get) | Returns one API Key by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [APIKey.list](/business/nouns/api-key/list) | Returns API Keys, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | An API Key is kept forever and never edited: it has no `update` or `delete`. ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `APIKey.get` | Yes | Yes | Yes | Yes | | `APIKey.list` | Yes | Yes | Yes | Yes | | `APIKey.issue` | Yes | Yes | Yes | No | | `APIKey.revoke` | Yes | Yes | Yes | No | | `APIKey.roll` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Issue the API key “Nightly sync” with a customer. ``` **API** ```bash curl -X POST https://api.sb/tutorloop.com/api-keys/issue \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"customer":"customer_1","name":"Nightly sync","environment":"test"}' ``` ```json { "api": "https://api.sb/tutorloop.com", "apiKey": { "$id": "https://api.sb/tutorloop.com/api-keys/api_key_1", "$type": "APIKey", "name": "Nightly sync", "environment": "test" }, "secret": "sk_live_4f2a…", "action": { "$id": "https://api.sb/tutorloop.com/actions/action_1", "operation": "APIKey.issue", "status": "done" }, "links": { "self": "https://api.sb/tutorloop.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { apiKey, secret } = await $.APIKey.issue({ customer: 'customer_1', name: 'Nightly sync', environment: 'test' }) ``` **CLI** ```bash npx startup-builder do APIKey.issue --json '{"customer":"customer_1","name":"Nightly sync","environment":"test"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.APIKey.issue({ customer: 'customer_1', name: 'Nightly sync', environment: 'test' })" } } ``` ## Example Leaseline sells renewal dates through its API. A property manager's admin issues a `live` key named `Nightly sync` that may call only `Collection.query`, and the [Portal](/business/nouns/portal) shows it as `leaseline_sk_live_4f2a`. When the key turns up in a public repository, it is revoked within minutes and the admins get an email to roll a replacement. # issue URL: /business/nouns/api-key/issue · Id: `verb:APIKey.issue` · Call: `await $.APIKey.issue({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Issue creates an API Key for one Customer and returns its secret once; afterwards only the prefix shows. [Issue](/business/nouns/issue) creates an [API Key](/business/nouns/api-key) for one [Customer](/business/nouns/customer) and returns its secret once; afterwards only the prefix shows. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `customer` | [Customer](/business/nouns/customer) | Yes | The Customer whose calls it signs. | | `name` | `string` | Yes | What the key is for. | | `environment` | `string` | Yes | One of `test` or `live`. | | `verbs` | list of [Verb](/business/nouns/verb) | No | The Verbs it may call; unset reaches every Verb the Customer’s Entitlements grant. | | `expiresAt` | `datetime` | No | When it stops working on its own. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `apiKey` | [API Key](/business/nouns/api-key) | Yes | The API Key, with its prefix. | | `secret` | `string` | Yes | The full secret. It is returned here once and never again. | ## Effects - Emits [`APIKey.issued`](/business/events/APIKey.issued). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Lists the key in the Customer’s Portal, with its prefix, scope and last use. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [APIKey.issue](/business/nouns/api-key/issue) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Issue the API key “Nightly sync” with a customer. ``` **API** ```bash curl -X POST https://api.sb/tutorloop.com/api-keys/issue \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"customer":"customer_1","name":"Nightly sync","environment":"test"}' ``` ```json { "api": "https://api.sb/tutorloop.com", "apiKey": { "$id": "https://api.sb/tutorloop.com/api-keys/api_key_1", "$type": "APIKey", "name": "Nightly sync", "environment": "test" }, "secret": "sk_live_4f2a…", "action": { "$id": "https://api.sb/tutorloop.com/actions/action_1", "operation": "APIKey.issue", "status": "done" }, "links": { "self": "https://api.sb/tutorloop.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { apiKey, secret } = await $.APIKey.issue({ customer: 'customer_1', name: 'Nightly sync', environment: 'test' }) ``` **CLI** ```bash npx startup-builder do APIKey.issue --json '{"customer":"customer_1","name":"Nightly sync","environment":"test"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.APIKey.issue({ customer: 'customer_1', name: 'Nightly sync', environment: 'test' })" } } ``` # revoke URL: /business/nouns/api-key/revoke · Id: `verb:APIKey.revoke` · Call: `await $.APIKey.revoke({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Revoke stops an API Key at once: its next call fails with 401, and the record and its history stay. Revoke stops an [API Key](/business/nouns/api-key) at once: its next call fails with 401, and the record and its history stay. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `apiKey` | [API Key](/business/nouns/api-key) | Yes | The API Key to stop. | | `reason` | `text` | No | Why, shown to the Customer’s admins. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `apiKey` | [API Key](/business/nouns/api-key) | Yes | The API Key, with `revokedAt` set. | ## Effects - Emits [`APIKey.revoked`](/business/events/APIKey.revoked). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Emails the Customer’s admins which key stopped, and why. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [APIKey.revoke](/business/nouns/api-key/revoke) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Revoke the latest API key. ``` **API** ```bash curl -X POST https://api.sb/shiftnote.app/api-keys/api_key_1/revoke \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/shiftnote.app", "apiKey": { "$id": "https://api.sb/shiftnote.app/api-keys/api_key_1", "$type": "APIKey", "name": "Nightly sync", "environment": "test" }, "action": { "$id": "https://api.sb/shiftnote.app/actions/action_1", "operation": "APIKey.revoke", "status": "done" }, "links": { "self": "https://api.sb/shiftnote.app/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const apiKey = await $.APIKey.revoke({ apiKey: 'api_key_1' }) ``` **CLI** ```bash npx startup-builder do APIKey.revoke --json '{"apiKey":"api_key_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.APIKey.revoke({ apiKey: 'api_key_1' })" } } ``` # roll URL: /business/nouns/api-key/roll · Id: `verb:APIKey.roll` · Call: `await $.APIKey.roll({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Roll issues a replacement API Key with the same scope and keeps the old one working until a set time. Roll issues a replacement [API Key](/business/nouns/api-key) with the same scope and keeps the old one working until a set time. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `apiKey` | [API Key](/business/nouns/api-key) | Yes | The API Key to replace. | | `expireIn` | `string` | No | How long the old key keeps working, from `0h` to `7d`. Defaults to `24h`. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `apiKey` | [API Key](/business/nouns/api-key) | Yes | The replacement API Key. | | `secret` | `string` | Yes | The replacement’s full secret, returned once. | ## Effects - Emits [`APIKey.rolled`](/business/events/APIKey.rolled). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Sets the old key’s `expiresAt`; every call it signs after that fails with 401 `unauthorized`. - Emails the Customer’s admins that the key changed, and when the old one stops. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [APIKey.roll](/business/nouns/api-key/roll) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Roll the latest API key. ``` **API** ```bash curl -X POST https://api.sb/tutorloop.com/api-keys/api_key_1/roll \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/tutorloop.com", "apiKey": { "$id": "https://api.sb/tutorloop.com/api-keys/api_key_1", "$type": "APIKey", "name": "Nightly sync", "environment": "test" }, "secret": "sk_live_9c1e…", "action": { "$id": "https://api.sb/tutorloop.com/actions/action_1", "operation": "APIKey.roll", "status": "done" }, "links": { "self": "https://api.sb/tutorloop.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { apiKey, secret } = await $.APIKey.roll({ apiKey: 'api_key_1' }) ``` **CLI** ```bash npx startup-builder do APIKey.roll --json '{"apiKey":"api_key_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.APIKey.roll({ apiKey: 'api_key_1' })" } } ``` Guides that call it: [Replace a leaked key](/products/api/replace-a-leaked-key). # App URL: /business/nouns/app · Id: `noun:app` > An App is an Interface where people work with a Product’s Nouns and Verbs through screens, backed by its API. An App is an [Interface](/business/nouns/interface) where people work with a [Product](/business/nouns/product)’s [Nouns](/business/nouns/noun) and [Verbs](/business/nouns/verb) through screens, backed by its API. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `personas` | list of [Persona](/business/nouns/persona) | No | The Personas it serves. | | `views` | list of [Dashboard](/business/nouns/dashboard) | No | Its Dashboards, compiled by default from the Persona’s Role: a list and record per Noun, a form per Verb. | | `slots` | `json` | No | Named places where a Component replaces a default part, such as a record header or the ask control. |
Inherited from [Interface](/business/nouns/interface): 3 properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `kind` | `string` | Yes | One of `api`, `mcp`, `cli`, `sdk`, `site`, `app`, `docs`, or `webhooks`. | | `path` | `string` | No | Where it is mounted on its Domain, such as `/api`. | | `conformsTo` | `json` | No | The Standards it also speaks, each mapping the Standard’s operations onto the Product’s Verbs. |
## Object ```json { "$id": "https://api.sb/routewise.dev/apps/app_1", "$type": "App", "kind": "api", "path": "/", "conformsTo": { "standard": "openai-chat", "operations": { "chat.completions.create": "Listing.write" } }, "personas": [ "persona_1" ], "views": [ "dashboard_1" ], "slots": {} } ``` ## Relationships - An App **guides** many [Flows](/business/nouns/flow): the [Flows](/business/nouns/flow) an App runs on first sign-in, one per [Persona](/business/nouns/persona) and [Offer](/business/nouns/offer), each ending at the activation [Event](/business/nouns/event). `guides`, inverse [`app`](/business/nouns/flow#rel-app). - An App **presents** many [Dashboards](/business/nouns/dashboard): an App opens on [Dashboards](/business/nouns/dashboard) for the people signed in to it. `presents`, inverse [`presentedIn`](/business/nouns/dashboard#rel-presented-in). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [App.publish](/business/nouns/app/publish) | Publish releases an App to its Customers, so each Tenant runs its newest build. | [Engineering Lead](/agents/engineering/engineering-lead) | [`App.published`](/business/events/App.published) | None. | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `App.publish` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Publish the app “Grain-free kibble, 12 lb”. ``` **API** ```bash curl -X POST https://api.sb/petpantry.shop/apps/app_1/publish \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/petpantry.shop", "app": { "$id": "https://api.sb/petpantry.shop/apps/app_1", "$type": "App", "kind": "api" }, "action": { "$id": "https://api.sb/petpantry.shop/actions/action_1", "operation": "App.publish", "status": "done" }, "links": { "self": "https://api.sb/petpantry.shop/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const app = await $.App.publish({ app: 'app_1' }) ``` **CLI** ```bash npx startup-builder do App.publish --json '{"app":"app_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.App.publish({ app: 'app_1' })" } } ``` ## Example The App of an invoicing [Software](/business/nouns/software) Product shows each [Invoice](/business/nouns/invoice) on a screen with `bill` and `void` buttons. Each button calls the same API a script calls. # publish URL: /business/nouns/app/publish · Id: `verb:App.publish` · Call: `await $.App.publish({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Publish releases an App to its Customers, so each Tenant runs its newest build. Publish releases an [App](/business/nouns/app) to its [Customers](/business/nouns/customer), so each [Tenant](/business/nouns/tenant) runs its newest build. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `app` | [App](/business/nouns/app) | Yes | The App to release. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `app` | [App](/business/nouns/app) | Yes | The App, now released. | ## Effects - Emits [`App.published`](/business/events/App.published). - Performed by the [Engineering Lead](/agents/engineering/engineering-lead). - Keeps the previous build, so a `revert` restores it. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [App.publish](/business/nouns/app/publish) | | The record is not in a state that allows this Verb, so the call is refused. | [`refused`](/code/api/errors/refused) | Read the record, run the Verb that moves it to an allowed state, then retry. | [App.publish](/business/nouns/app/publish) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Medium: two-way, visible | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | 1 business hour, in which a watcher can pause, redirect or cancel it; then it runs. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Publish the app “Grain-free kibble, 12 lb”. ``` **API** ```bash curl -X POST https://api.sb/petpantry.shop/apps/app_1/publish \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/petpantry.shop", "app": { "$id": "https://api.sb/petpantry.shop/apps/app_1", "$type": "App", "kind": "api" }, "action": { "$id": "https://api.sb/petpantry.shop/actions/action_1", "operation": "App.publish", "status": "done" }, "links": { "self": "https://api.sb/petpantry.shop/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const app = await $.App.publish({ app: 'app_1' }) ``` **CLI** ```bash npx startup-builder do App.publish --json '{"app":"app_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.App.publish({ app: 'app_1' })" } } ``` Guides that call it: [Build my app](/products/app/build-my-app). # approve URL: /business/nouns/approval/approve · Id: `verb:Approval.approve` · Call: `await $.Approval.approve({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Approve allows the pending Action an Approval holds, and that Action runs. Approve allows the pending [Action](/business/nouns/action) an [Approval](/business/nouns/approval) holds, and that Action runs. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `approval` | [Approval](/business/nouns/approval) | Yes | The open Approval. | | `note` | `text` | No | Why it is approved. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `approval` | [Approval](/business/nouns/approval) | Yes | The approved Approval. | ## Effects - Emits [`Approval.approved`](/business/events/Approval.approved). - Performed by the [Founder](/agents/founding/founder). - Guards run first, then Evaluators where a Policy enables them, and a Human approves only above the stakes threshold. - Counts a chat press only from an account linked to a Human who holds the Permission for the Action’s scope. - Records the first valid answer; the chat card updates in place, and a later press returns that verdict. - Asks the approver to sign in first when a one-way Action is at or above the stakes threshold. - Records the answer as an Action via chat, with the message it came from. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Approval.approve](/business/nouns/approval/approve) | | The record is not in a state that allows this Verb, so the call is refused. | [`refused`](/code/api/errors/refused) | Read the record, run the Verb that moves it to an allowed state, then retry. | [Approval.approve](/business/nouns/approval/approve) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Approve the latest approval. ``` **API** ```bash curl -X POST https://api.sb/kilnbakery.com/approvals/approval_1/approve \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/kilnbakery.com", "approval": { "$id": "https://api.sb/kilnbakery.com/approvals/approval_1", "$type": "Approval", "status": "pending", "mode": "try" }, "action": { "$id": "https://api.sb/kilnbakery.com/actions/action_1", "operation": "Approval.approve", "status": "done" }, "links": { "self": "https://api.sb/kilnbakery.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const approval = await $.Approval.approve({ approval: 'approval_1' }) ``` **CLI** ```bash npx startup-builder do Approval.approve --json '{"approval":"approval_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Approval.approve({ approval: 'approval_1' })" } } ``` Guides that call it: [Approve what agents spend](/agents/approve-what-agents-spend), [Answer an approval](/agents/answer-an-approval). # Approval URL: /business/nouns/approval · Id: `noun:approval` > An Approval is a Task to allow or refuse one pending Action that exceeds a Limit or a Mandate. An Approval is a [Task](/business/nouns/task) to allow or refuse one pending [Action](/business/nouns/action) that exceeds a [Limit](/business/nouns/limit) or a [Mandate](/business/nouns/mandate). ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `verdict` | `string` | No | One of `allowed` or `refused`. | | `deadline` | `datetime` | No | When an unanswered Approval cancels the Action. |
Inherited from [Task](/business/nouns/task): 3 properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `due` | `datetime` | No | When the Task is due. | | `priority` | `integer` | No | Its rank in the inbox, highest first. | | `recurrence` | `string` | No | The schedule a recurring duty repeats on. |
Inherited from [Action](/business/nouns/action): 11 properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `status` | `string` | Yes | One of `pending`, `done`, `failed`, `canceled`, or `refused`. | | `reason` | `string` | No | Why a pending Action waits: `queued`, `running`, `retrying`, `awaitingWorker`, `awaitingInput`, `awaitingSource`, `awaitingAction`, or `awaitingTime`. | | `mode` | `string` | Yes | How the caller invoked it: `try`, `send`, or `do`. | | `by` | [Worker](/business/nouns/worker) | No | The Worker that performed it. | | `for` | [Party](/business/nouns/party) | No | The Party it was done on behalf of. | | `via` | `string` | No | The Interface or request it arrived through. | | `on` | `string` | No | The Action or Event that caused it, such as the failed attempt a retry follows. | | `thing` | `string` | No | The record, at the Version the Action was decided against. | | `input` | `json` | No | The input it was called with. | | `createdAt` | `datetime` | No | When it was called. | | `reserved` | `money` | No | The most this Action may cost, held against its Limits from the check until it settles, billed misses included. |
## Object ```json { "$id": "https://api.sb/shiftnote.app/approvals/approval_1", "$type": "Approval", "status": "pending", "reason": "queued", "mode": "try", "by": "worker_1", "for": "party_1", "via": "API", "on": "Invoice.overdue", "thing": "invoice_1@v3", "input": {}, "createdAt": "2026-10-22T12:00:00Z", "reserved": { "amount": 79, "currency": "USD" }, "due": "2026-10-22T12:00:00Z", "priority": 1, "recurrence": "Weekly on Friday", "verdict": "allowed", "deadline": "2026-10-22T12:00:00Z" } ``` ## Relationships - An Approval **gates** one [Action](/business/nouns/action): an Approval holds one pending [Action](/business/nouns/action) that exceeds a [Limit](/business/nouns/limit) or [Mandate](/business/nouns/mandate) until someone allows or refuses it. `gates`, inverse [`approvals`](/business/nouns/action#rel-approvals). ## Lifecycle | State | Meaning | Moves to | | --- | --- | --- | | `pending` (first) | An Action waits on the answer. | `approved` by [Approval.approve](/business/nouns/approval/approve); `refused` by [Approval.refuse](/business/nouns/approval/refuse); `expired` on [`Approval.expired`](/business/nouns/approval#approvalexpired) when nobody answered by its `deadline` | | `approved` | The Action it held runs. | None: it ends here. | | `refused` | The Action it held ends `refused`, with the reason given. | None: it ends here. | | `expired` | Nobody answered by the deadline, so the Action it held ends `canceled`. | None: it ends here. | ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Approval.approve](/business/nouns/approval/approve) | Approve allows the pending Action an Approval holds, and that Action runs. | [Founder](/agents/founding/founder) | [`Approval.approved`](/business/events/Approval.approved) | None. | | [Approval.refuse](/business/nouns/approval/refuse) | Refuse declines an Approval, which sets the Action it holds to `refused` with the reason given. | [Founder](/agents/founding/founder) | [`Approval.refused`](/business/events/Approval.refused) | None. | | [Approval.create](/business/nouns/approval/create) | Creates an Approval. Inherited from [Noun](/business/nouns/noun). | None. | `Approval.created` | Two-way: `try`, `send`, `do` | | [Approval.get](/business/nouns/approval/get) | Returns one Approval by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Approval.list](/business/nouns/approval/list) | Returns Approvals, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Approval.update](/business/nouns/approval/update) | Changes the given properties of an Approval. Inherited from [Noun](/business/nouns/noun). | None. | `Approval.updated` | Two-way: `try`, `send`, `do` | | [Approval.delete](/business/nouns/approval/delete) | Deletes an Approval; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Approval.deleted` | One-way: `send`, `do` | ## Events Events no Verb emits. Each Verb’s Event is in the Verbs table above; every Event is delivered in the same shape. ### Approval.expired Nobody answered an Approval by its `deadline`, so the Action it held ends. Raised by a clock. | Field | Type | Required | Description | | --- | --- | --- | --- | | `name` | `string` | Yes | `Approval.expired`. | | `at` | `datetime` | Yes | When it happened. | | `seq` | `integer` | No | Its position in the namespace, one more than the Event before; any seq is a cursor into the history. | | `data` | `json` | Yes | The Thing as the Action left it. | | `data.approval` | [Approval](/business/nouns/approval) | Yes | The Approval as the change left it. | | `data.approval.status` | `string` | Yes | One of `pending`, `done`, `failed`, `canceled`, or `refused`. | | `data.approval.reason` | `string` | No | Why a pending Action waits: `queued`, `running`, `retrying`, `awaitingWorker`, `awaitingInput`, `awaitingSource`, `awaitingAction`, or `awaitingTime`. | | `data.approval.mode` | `string` | Yes | How the caller invoked it: `try`, `send`, or `do`. | | `data.approval.by` | [Worker](/business/nouns/worker) | No | The Worker that performed it. | | `data.approval.for` | [Party](/business/nouns/party) | No | The Party it was done on behalf of. | | `data.approval.via` | `string` | No | The Interface or request it arrived through. | | `data.approval.on` | `string` | No | The Action or Event that caused it, such as the failed attempt a retry follows. | | `data.approval.thing` | `string` | No | The record, at the Version the Action was decided against. | | `data.approval.input` | `json` | No | The input it was called with. | | `data.approval.createdAt` | `datetime` | No | When it was called. | | `data.approval.reserved` | `money` | No | The most this Action may cost, held against its Limits from the check until it settles, billed misses included. | | `data.approval.due` | `datetime` | No | When the Task is due. | | `data.approval.priority` | `integer` | No | Its rank in the inbox, highest first. | | `data.approval.recurrence` | `string` | No | The schedule a recurring duty repeats on. | | `data.approval.verdict` | `string` | No | One of `allowed` or `refused`. | | `data.approval.deadline` | `datetime` | No | When an unanswered Approval cancels the Action. | ```json { "$id": "https://api.sb/shiftnote.app/events/event_1", "$type": "Event", "name": "Approval.expired", "at": "2026-10-22T12:00:00Z", "data": { "approval": { "$id": "https://api.sb/shiftnote.app/approvals/approval_1", "$type": "Approval", "status": "pending", "reason": "queued", "mode": "try", "by": "worker_1", "for": "party_1", "via": "API", "on": "Invoice.overdue", "thing": "invoice_1@v3", "input": {}, "createdAt": "2026-10-22T12:00:00Z", "reserved": { "amount": 79, "currency": "USD" }, "due": "2026-10-22T12:00:00Z", "priority": 1, "recurrence": "Weekly on Friday", "verdict": "allowed", "deadline": "2026-10-22T12:00:00Z" } }, "seq": 1 } ``` ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Approval.create` | Yes | Yes | Yes | No | | `Approval.get` | Yes | Yes | Yes | Yes | | `Approval.list` | Yes | Yes | Yes | Yes | | `Approval.update` | Yes | Yes | Yes | No | | `Approval.delete` | Yes | Yes | Yes | No | | `Approval.approve` | Yes | Yes | Yes | No | | `Approval.refuse` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Approve the latest approval. ``` **API** ```bash curl -X POST https://api.sb/kilnbakery.com/approvals/approval_1/approve \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/kilnbakery.com", "approval": { "$id": "https://api.sb/kilnbakery.com/approvals/approval_1", "$type": "Approval", "status": "pending", "mode": "try" }, "action": { "$id": "https://api.sb/kilnbakery.com/actions/action_1", "operation": "Approval.approve", "status": "done" }, "links": { "self": "https://api.sb/kilnbakery.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const approval = await $.Approval.approve({ approval: 'approval_1' }) ``` **CLI** ```bash npx startup-builder do Approval.approve --json '{"approval":"approval_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Approval.approve({ approval: 'approval_1' })" } } ``` ## Example The [Sales Lead](/agents/sales/sales-lead) offers a 30% discount when its [Limit](/business/nouns/limit) is 20%. An Approval lands in the [Founder](/agents/founding/founder)'s inbox, and the [Quote](/business/nouns/quote) goes out once approved. # refuse URL: /business/nouns/approval/refuse · Id: `verb:Approval.refuse` · Call: `await $.Approval.refuse({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Refuse declines an Approval, which sets the Action it holds to `refused` with the reason given. Refuse declines an [Approval](/business/nouns/approval), which sets the [Action](/business/nouns/action) it holds to `refused` with the reason given. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `approval` | [Approval](/business/nouns/approval) | Yes | The open Approval. | | `reason` | `text` | Yes | Why it is refused. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `approval` | [Approval](/business/nouns/approval) | Yes | The refused Approval. | ## Effects - Emits [`Approval.refused`](/business/events/Approval.refused). - Performed by the [Founder](/agents/founding/founder). - Counts a chat press only from an account linked to a Human who holds the Permission for the Action’s scope. - Records the first valid answer; the chat card updates in place, and a later press returns that verdict. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Approval.refuse](/business/nouns/approval/refuse) | | The record is not in a state that allows this Verb, so the call is refused. | [`refused`](/code/api/errors/refused) | Read the record, run the Verb that moves it to an allowed state, then retry. | [Approval.refuse](/business/nouns/approval/refuse) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Refuse the latest approval. ``` **API** ```bash curl -X POST https://api.sb/routewise.dev/approvals/approval_1/refuse \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"reason":"Example reason"}' ``` ```json { "api": "https://api.sb/routewise.dev", "approval": { "$id": "https://api.sb/routewise.dev/approvals/approval_1", "$type": "Approval", "status": "refused", "mode": "try" }, "action": { "$id": "https://api.sb/routewise.dev/actions/action_1", "operation": "Approval.refuse", "status": "done" }, "links": { "self": "https://api.sb/routewise.dev/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const approval = await $.Approval.refuse({ approval: 'approval_1', reason: 'Example reason' }) ``` **CLI** ```bash npx startup-builder do Approval.refuse --json '{"approval":"approval_1","reason":"Example reason"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Approval.refuse({ approval: 'approval_1', reason: 'Example reason' })" } } ``` # Attestation URL: /business/nouns/attestation · Id: `noun:attestation` > An Attestation is the signed, frozen act by which a credentialed Worker performs or declines a Reserved Act. An Attestation is the signed, frozen act by which a credentialed [Worker](/business/nouns/worker) performs or declines a [Reserved Act](/business/nouns/reserved-act). ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `outcome` | `string` | Yes | One of `performed` or `declined`. | | `signedAt` | `datetime` | Yes | When the Worker signed it. | ## Object ```json { "$id": "https://api.sb/kilnbakery.com/attestations/attestation_1", "$type": "Attestation", "outcome": "performed", "signedAt": "2026-10-22T12:00:00Z" } ``` ## Relationships - An Attestation **performs** one [Reserved Act](/business/nouns/reserved-act): the [Reserved Act](/business/nouns/reserved-act) the Attestation records as performed or declined. `performs`, inverse [`attestations`](/business/nouns/reserved-act#rel-attestations). - An Attestation **is signed under** one [Credential](/business/nouns/credential): the [Credential](/business/nouns/credential) the signing [Worker](/business/nouns/worker) held when it signed. `signedUnder`, inverse [`attestations`](/business/nouns/credential#rel-attestations). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Attestation.create](/business/nouns/attestation/create) | Creates an Attestation. Inherited from [Noun](/business/nouns/noun). | None. | `Attestation.created` | Two-way: `try`, `send`, `do` | | [Attestation.get](/business/nouns/attestation/get) | Returns one Attestation by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Attestation.list](/business/nouns/attestation/list) | Returns Attestations, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | An Attestation is kept forever and never edited: it has no `update` or `delete`. ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Attestation.create` | Yes | Yes | Yes | No | | `Attestation.get` | Yes | Yes | Yes | Yes | | `Attestation.list` | Yes | Yes | Yes | Yes | ## Call it **Ask** ```text Add an attestation to PetPantry. ``` **API** ```bash curl -X POST https://api.sb/petpantry.shop/attestations \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"outcome":"performed","signedAt":"2026-10-22T12:00:00Z"}' ``` ```json { "api": "https://api.sb/petpantry.shop", "attestation": { "$id": "https://api.sb/petpantry.shop/attestations/attestation_1", "$type": "Attestation", "outcome": "performed", "signedAt": "2026-10-22T12:00:00Z" }, "action": { "$id": "https://api.sb/petpantry.shop/actions/action_1", "operation": "Attestation.create", "status": "done" }, "links": { "self": "https://api.sb/petpantry.shop/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const attestation = await $.Attestation.create({ outcome: 'performed', signedAt: '2026-10-22T12:00:00Z' }) ``` **CLI** ```bash npx startup-builder do Attestation.create --json '{"outcome":"performed","signedAt":"2026-10-22T12:00:00Z"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Attestation.create({ outcome: 'performed', signedAt: '2026-10-22T12:00:00Z' })" } } ``` ## Example A licensed appraiser reviews a valuation report, finds no conflict, and signs. The Attestation freezes the report, the signature, and the appraiser's standing at that moment. # Audience URL: /business/nouns/audience · Id: `noun:audience` > An Audience is a saved query over Visitors, Leads, Prospects, or Customers, used to target Ads and Messages. An Audience is a saved query over [Visitors](/business/nouns/visitor), [Leads](/business/nouns/lead), [Prospects](/business/nouns/prospect), or [Customers](/business/nouns/customer), used to target [Ads](/business/nouns/ad) and [Messages](/business/nouns/message). ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `size` | `integer` | No | How many people match. |
Inherited from [Collection](/business/nouns/collection): 1 property | Property | Type | Required | Description | | --- | --- | --- | --- | | `query` | `json` | No | The saved query that defines a dynamic Collection. |
Inherited from [Thing](/business/nouns/thing): 4 properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `id` | `string` | Yes | The stable identifier, which never changes. | | `type` | list of [Noun](/business/nouns/noun) | Yes | The Nouns this Thing is an instance of. | | `state` | `string` | No | The current state in its lifecycle. | | `outside` | `json` | No | The ids this Thing has in outside tools, one per Integration, so a re-run matches instead of duplicating. |
## Object ```json { "$id": "https://api.sb/tutorloop.com/audiences/audience_1", "$type": "Audience", "id": "Example id", "type": [ "noun_1" ], "state": "Example state", "outside": {}, "query": {}, "size": 1 } ``` ## Relationships - An Audience **is targeted by** many [Ads](/business/nouns/ad): an [Ad](/business/nouns/ad) is shown to the people its Audiences select. `targetedBy`, inverse [`targets`](/business/nouns/ad#rel-targets). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Audience.create](/business/nouns/audience/create) | Creates an Audience. Inherited from [Noun](/business/nouns/noun). | None. | `Audience.created` | Two-way: `try`, `send`, `do` | | [Audience.get](/business/nouns/audience/get) | Returns one Audience by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Audience.list](/business/nouns/audience/list) | Returns Audiences, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Audience.update](/business/nouns/audience/update) | Changes the given properties of an Audience. Inherited from [Noun](/business/nouns/noun). | None. | `Audience.updated` | Two-way: `try`, `send`, `do` | | [Audience.delete](/business/nouns/audience/delete) | Deletes an Audience; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Audience.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Audience.create` | Yes | Yes | Yes | No | | `Audience.get` | Yes | Yes | Yes | Yes | | `Audience.list` | Yes | Yes | Yes | Yes | | `Audience.update` | Yes | Yes | Yes | No | | `Audience.delete` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Add an audience to QuietCopy with a noun. ``` **API** ```bash curl -X POST https://api.sb/quietcopy.com/audiences \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"id":"audience_1","type":["noun_1"]}' ``` ```json { "api": "https://api.sb/quietcopy.com", "audience": { "$id": "https://api.sb/quietcopy.com/audiences/audience_1", "$type": "Audience", "id": "Example id", "type": [ "noun_1" ] }, "action": { "$id": "https://api.sb/quietcopy.com/actions/action_1", "operation": "Audience.create", "status": "done" }, "links": { "self": "https://api.sb/quietcopy.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const audience = await $.Audience.create({ id: 'audience_1', type: ['noun_1'] }) ``` **CLI** ```bash npx startup-builder do Audience.create --json '{"id":"audience_1","type":["noun_1"]}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Audience.create({ id: 'audience_1', type: ['noun_1'] })" } } ``` ## Example The Audience of trial users with no API call in 7 days feeds a reminder Message each morning. It drops anyone who becomes a [Customer](/business/nouns/customer). # Audit URL: /business/nouns/audit · Id: `noun:audit` > An Audit is one engagement with an outside firm: the namespaces in scope, the Criteria, the report period, and the firm’s Attestation. An Audit is one engagement with an outside firm: the namespaces in scope, the [Criteria](/business/nouns/criterion), the report period, and the firm’s [Attestation](/business/nouns/attestation). ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `firm` | [Organization](/business/nouns/organization) | Yes | The licensed firm that performs the engagement. | | `criteria` | list of [Criterion](/business/nouns/criterion) | Yes | The Criteria in scope. | | `type` | `string` | Yes | One of `type1` (one date) or `type2` (a range). | | `from` | `datetime` | Yes | The first day of the report period; never before the namespace’s first Event. | | `to` | `datetime` | Yes | The last day of the report period. | | `seed` | `string` | Yes | The sampling seed, committed before the period ends. | | `attestation` | [Attestation](/business/nouns/attestation) | No | The firm’s signed opinion. | ## Object ```json { "$id": "https://api.sb/patentpad.com/audits/audit_1", "$type": "Audit", "firm": "organization_1", "criteria": [ "criterion_1" ], "type": "Example type", "from": "2026-10-22T12:00:00Z", "to": "2026-10-22T12:00:00Z", "seed": "Example seed", "attestation": "attestation_1" } ``` ## Relationships - An Audit **relies on** many [Proofs](/business/nouns/proof): the [Proofs](/business/nouns/proof) the auditing firm samples across the report period. `reliesOn`, inverse [`reliedOnBy`](/business/nouns/proof#rel-relied-on-by). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Audit.get](/business/nouns/audit/get) | Returns one Audit by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Audit.list](/business/nouns/audit/list) | Returns Audits, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | An Audit is kept forever and never edited: it has no `update` or `delete`. ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Audit.get` | Yes | Yes | Yes | Yes | | `Audit.list` | Yes | Yes | Yes | Yes | ## Call it **Ask** ```text Show me the latest audit. ``` **API** ```bash curl https://api.sb/shiftnote.app/audits/audit_1 \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/shiftnote.app", "$type": "Audit", "$id": "https://api.sb/shiftnote.app/audits/audit_1", "audit": { "$id": "https://api.sb/shiftnote.app/audits/audit_1", "$type": "Audit", "firm": "organization_1", "criteria": [ "criterion_1" ], "type": "Example type", "from": "2026-10-22T12:00:00Z" }, "links": { "self": "https://api.sb/shiftnote.app/audits/audit_1", "up": "https://api.sb/shiftnote.app/audits" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const audit = await $.Audit.get({ id: 'audit_1' }) ``` **CLI** ```bash npx startup-builder do Audit.get --json '{"id":"audit_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Audit.get({ id: 'audit_1' })" } } ``` ## Example A firm signs an engagement letter for a type 2 report over the first six months of the year. Signing creates the Audit, opens the firm's read-only namespace, and commits the sampling seed. # approve URL: /business/nouns/bill/approve · Id: `verb:Bill.approve` · Call: `await $.Bill.approve({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Approve accepts a coded Bill for payment within the approver’s Mandate and schedules it for its due date. Approve accepts a coded [Bill](/business/nouns/bill) for payment within the approver’s [Mandate](/business/nouns/mandate) and schedules it for its due date. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `bill` | [Bill](/business/nouns/bill) | Yes | The coded Bill. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `bill` | [Bill](/business/nouns/bill) | Yes | The approved Bill, scheduled for its due date. | ## Effects - Emits [`Bill.approved`](/business/events/Bill.approved). - Performed by the [Finance Lead](/agents/finance/finance-lead). - One-way (money): it waits out its delay window, and runs in the `send` and `do` modes. - Above the Mandate’s Limit, waits for an Approval from the Founder. - Schedules `Bill.pay` for the due date. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Bill.approve](/business/nouns/bill/approve) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Medium: one-way, bounded (money) | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | 1 business hour, in which a watcher can pause, redirect or cancel it; then it runs. | | Limit | The spend [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) or [Mandate](/business/nouns/mandate) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Approve the latest bill. ``` **API** ```bash curl -X POST https://api.sb/quietcopy.com/bills/bill_1/approve \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/quietcopy.com", "bill": { "$id": "https://api.sb/quietcopy.com/bills/bill_1", "$type": "Bill", "organization": "organization_1", "amount": { "amount": 39, "currency": "USD" }, "dueOn": "2026-10-22", "status": "received" }, "action": { "$id": "https://api.sb/quietcopy.com/actions/action_1", "operation": "Bill.approve", "status": "done" }, "links": { "self": "https://api.sb/quietcopy.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const bill = await $.Bill.approve({ bill: 'bill_1' }) ``` **CLI** ```bash npx startup-builder do Bill.approve --json '{"bill":"bill_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Bill.approve({ bill: 'bill_1' })" } } ``` Next: [`Bill.pay`](/business/nouns/bill/pay) (in `guide:pay-a-supplier`). Guides that call it: [Pay a supplier](/systems/finance/pay-a-supplier). # Bill URL: /business/nouns/bill · Id: `noun:bill` > A Bill is an amount a Startup owes an outside Organization, coded to an account, approved within a Mandate, and paid by its due date. A Bill is an amount a [Startup](/business/nouns/startup) owes an outside [Organization](/business/nouns/organization), coded to an account, approved within a [Mandate](/business/nouns/mandate), and paid by its due date. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `organization` | [Organization](/business/nouns/organization) | Yes | The Organization the Startup owes. | | `amount` | `money` | Yes | What the Bill asks for, in its currency. | | `dueOn` | `date` | Yes | The date payment is due; an approved Bill is paid on it. | | `account` | `string` | No | The chart-of-accounts code it is coded to, such as `expense.hosting`. | | `status` | `string` | Yes | Where the Bill stands; only an `approved` Bill is paid. | | `file` | [File](/business/nouns/file) | No | The File the Bill arrived as: an email attachment or an upload. | ## Object ```json { "$id": "https://api.sb/routewise.dev/bills/bill_1", "$type": "Bill", "organization": "organization_1", "amount": { "amount": 25, "currency": "USD" }, "dueOn": "2026-10-22", "account": "expense.hosting", "status": "received", "file": "file_1" } ``` ## Relationships - A Bill **is owed to** one [Organization](/business/nouns/organization): a Bill is owed to one outside [Organization](/business/nouns/organization), whose page lists every Bill the [Startup](/business/nouns/startup) owes it. `owedTo`, inverse [`bills`](/business/nouns/organization#rel-bills). ## Lifecycle | State | Meaning | Moves to | | --- | --- | --- | | `received` (first) | It arrived and is coded to an account, waiting for approval. | `approved` by [Bill.approve](/business/nouns/bill/approve) | | `approved` | Accepted within the approver’s Mandate and scheduled for its due date. | `paid` by [Bill.pay](/business/nouns/bill/pay) | | `paid` | Its amount is sent to the Organization and reconciled to Entries. | `approved` on [`Transaction.failed`](/business/nouns/transaction#transactionfailed) when the rail refused the Transaction that paid this Bill | ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Bill.approve](/business/nouns/bill/approve) | Approve accepts a coded Bill for payment within the approver’s Mandate and schedules it for its due date. | [Finance Lead](/agents/finance/finance-lead) | [`Bill.approved`](/business/events/Bill.approved) | One-way (money): `send`, `do` | | [Bill.pay](/business/nouns/bill/pay) | Pay sends an approved Bill’s amount to its Organization on the due date and reconciles the payment to Entries. | [Treasurer](/agents/finance/treasurer) | [`Bill.paid`](/business/events/Bill.paid) | One-way (money): `send`, `do` | | [Bill.create](/business/nouns/bill/create) | Creates a Bill. Inherited from [Noun](/business/nouns/noun). | None. | `Bill.created` | Two-way: `try`, `send`, `do` | | [Bill.get](/business/nouns/bill/get) | Returns one Bill by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Bill.list](/business/nouns/bill/list) | Returns Bills, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Bill.update](/business/nouns/bill/update) | Changes the given properties of a Bill. Inherited from [Noun](/business/nouns/noun). | None. | `Bill.updated` | Two-way: `try`, `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Bill.create` | Yes | Yes | Yes | No | | `Bill.get` | Yes | Yes | Yes | Yes | | `Bill.list` | Yes | Yes | Yes | Yes | | `Bill.update` | Yes | Yes | Yes | No | | `Bill.approve` | Yes | No | No | No | | `Bill.pay` | Yes | No | No | No | ## Call it **Ask** ```text Approve the latest bill. ``` **API** ```bash curl -X POST https://api.sb/quietcopy.com/bills/bill_1/approve \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/quietcopy.com", "bill": { "$id": "https://api.sb/quietcopy.com/bills/bill_1", "$type": "Bill", "organization": "organization_1", "amount": { "amount": 39, "currency": "USD" }, "dueOn": "2026-10-22", "status": "received" }, "action": { "$id": "https://api.sb/quietcopy.com/actions/action_1", "operation": "Bill.approve", "status": "done" }, "links": { "self": "https://api.sb/quietcopy.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const bill = await $.Bill.approve({ bill: 'bill_1' }) ``` **CLI** ```bash npx startup-builder do Bill.approve --json '{"bill":"bill_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Bill.approve({ bill: 'bill_1' })" } } ``` ## Example A hosting invoice for $640 arrives by email at a pet-supply store. It becomes a Bill coded to `expense.hosting`, the [Finance Lead](/agents/finance/finance-lead) approves it within its [Mandate](/business/nouns/mandate), and the [Treasurer](/agents/finance/treasurer) pays it on the 30th. # pay URL: /business/nouns/bill/pay · Id: `verb:Bill.pay` · Call: `await $.Bill.pay({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Pay sends an approved Bill’s amount to its Organization on the due date and reconciles the payment to Entries. Pay sends an approved [Bill](/business/nouns/bill)’s amount to its [Organization](/business/nouns/organization) on the due date and reconciles the payment to [Entries](/business/nouns/entry). ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `bill` | [Bill](/business/nouns/bill) | Yes | The approved Bill. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `transaction` | [Transaction](/business/nouns/transaction) | Yes | The payment Transaction. | | `bill` | [Bill](/business/nouns/bill) | Yes | The Bill, now paid. | ## Effects - Emits [`Bill.paid`](/business/events/Bill.paid). - Performed by the [Treasurer](/agents/finance/treasurer). - One-way (money): it waits out its delay window, and runs in the `send` and `do` modes. - Pays from the Startup’s Stripe balance or a linked bank account. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Bill.pay](/business/nouns/bill/pay) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Medium: one-way, bounded (money) | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | 1 business hour, in which a watcher can pause, redirect or cancel it; then it runs. | | Limit | The spend [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) or [Mandate](/business/nouns/mandate) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Pay the latest bill. ``` **API** ```bash curl -X POST https://api.sb/patentpad.com/bills/bill_1/pay \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/patentpad.com", "transaction": { "$id": "https://api.sb/patentpad.com/transactions/transaction_1", "$type": "Transaction", "kind": "charge", "amount": { "amount": 499, "currency": "USD" } }, "bill": { "$id": "https://api.sb/patentpad.com/bills/bill_1", "$type": "Bill", "organization": "organization_1", "amount": { "amount": 499, "currency": "USD" }, "dueOn": "2026-10-22", "status": "received" }, "action": { "$id": "https://api.sb/patentpad.com/actions/action_1", "operation": "Bill.pay", "status": "done" }, "links": { "self": "https://api.sb/patentpad.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { transaction, bill } = await $.Bill.pay({ bill: 'bill_1' }) ``` **CLI** ```bash npx startup-builder do Bill.pay --json '{"bill":"bill_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Bill.pay({ bill: 'bill_1' })" } } ``` Guides that call it: [Pay a supplier](/systems/finance/pay-a-supplier). # clear URL: /business/nouns/brand/clear · Id: `verb:Brand.clear` · Call: `await $.Brand.clear({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Clear checks a proposed Brand name against trademark registers, Domain availability and the Startup’s handles on outside platforms in one call. Clear checks a proposed [Brand](/business/nouns/brand) name against trademark registers, [Domain](/business/nouns/domain) availability and the [Startup](/business/nouns/startup)’s handles on outside platforms in one call. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `brand` | [Brand](/business/nouns/brand) | Yes | The Brand whose name to check. | | `markets` | list of [Market](/business/nouns/market) | No | The Markets whose registers to search. Defaults to the Startup’s Markets. | | `classes` | `integer[]` | No | Trademark classes. Defaults to the classes of the Startup’s Products. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `verdict` | `string` | Yes | `clear` lets the name ship, `conflict` blocks it, `review` waits for the Legal Lead. | | `findings` | `json` | Yes | Each similar mark, taken Domain or taken handle, with the register or platform it was found on. | | `brand` | [Brand](/business/nouns/brand) | Yes | The Brand whose name was checked. | ## Effects - Emits [`Brand.cleared`](/business/events/Brand.cleared). - Performed by the [Legal Lead](/agents/legal/legal-lead). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Refuses `Site.publish` under a Brand whose latest verdict is `conflict`. - Opens an Approval for the Legal Lead on `review`. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Brand.clear](/business/nouns/brand/clear) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Clear my brand. ``` **API** ```bash curl -X POST https://api.sb/petpantry.shop/brands/brand_1/clear \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/petpantry.shop", "verdict": "clear", "findings": {}, "brand": { "$id": "https://api.sb/petpantry.shop/brands/brand_1", "$type": "Brand", "name": "PetPantry" }, "action": { "$id": "https://api.sb/petpantry.shop/actions/action_1", "operation": "Brand.clear", "status": "done" }, "links": { "self": "https://api.sb/petpantry.shop/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { verdict, findings, brand } = await $.Brand.clear({ brand: 'brand_1' }) ``` **CLI** ```bash npx startup-builder do Brand.clear --json '{"brand":"brand_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Brand.clear({ brand: 'brand_1' })" } } ``` # Brand URL: /business/nouns/brand · Id: `noun:brand` > A Brand is a name, a voice, a logo, and a style under which a Startup makes Offers. A Brand is a name, a voice, a logo, and a style under which a [Startup](/business/nouns/startup) makes [Offers](/business/nouns/offer). ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `name` | `string` | Yes | The name customers see. | | `voice` | `text` | No | How the Brand writes and speaks. | | `logo` | `url` | No | The logo image. | ## Object ```json { "$id": "https://api.sb/shiftnote.app/brands/brand_1", "$type": "Brand", "name": "ShiftNote", "voice": "Reassuring and direct.", "logo": "https://shiftnote.app" } ``` ## Relationships - A Brand **brands** many [Offers](/business/nouns/offer): each [Offer](/business/nouns/offer) carries exactly one Brand, whose name, voice and logo the buyer sees. `brands`, inverse [`brandedBy`](/business/nouns/offer#rel-branded-by). - A Brand **styles** many [Sites](/business/nouns/site): a [Site](/business/nouns/site) renders one Brand’s name, voice and [Theme](/business/nouns/theme). `styles`, inverse [`styledBy`](/business/nouns/site#rel-styled-by). - A Brand **is themed by** one [Theme](/business/nouns/theme): a [Theme](/business/nouns/theme) sets a Brand’s color, type, spacing and motion. `themedBy`, inverse [`themes`](/business/nouns/theme#rel-themes). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Brand.clear](/business/nouns/brand/clear) | Clear checks a proposed Brand name against trademark registers, Domain availability and the Startup’s handles on outside platforms in one call. | [Legal Lead](/agents/legal/legal-lead) | [`Brand.cleared`](/business/events/Brand.cleared) | Two-way: `try`, `send`, `do` | | [Brand.create](/business/nouns/brand/create) | Creates a Brand. Inherited from [Noun](/business/nouns/noun). | None. | `Brand.created` | Two-way: `try`, `send`, `do` | | [Brand.get](/business/nouns/brand/get) | Returns one Brand by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Brand.list](/business/nouns/brand/list) | Returns Brands, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Brand.update](/business/nouns/brand/update) | Changes the given properties of a Brand. Inherited from [Noun](/business/nouns/noun). | None. | `Brand.updated` | Two-way: `try`, `send`, `do` | | [Brand.delete](/business/nouns/brand/delete) | Deletes a Brand; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Brand.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Brand.create` | Yes | Yes | Yes | No | | `Brand.get` | Yes | Yes | Yes | Yes | | `Brand.list` | Yes | Yes | Yes | Yes | | `Brand.update` | Yes | Yes | Yes | No | | `Brand.delete` | Yes | Yes | Yes | No | | `Brand.clear` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Clear my brand. ``` **API** ```bash curl -X POST https://api.sb/petpantry.shop/brands/brand_1/clear \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/petpantry.shop", "verdict": "clear", "findings": {}, "brand": { "$id": "https://api.sb/petpantry.shop/brands/brand_1", "$type": "Brand", "name": "PetPantry" }, "action": { "$id": "https://api.sb/petpantry.shop/actions/action_1", "operation": "Brand.clear", "status": "done" }, "links": { "self": "https://api.sb/petpantry.shop/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { verdict, findings, brand } = await $.Brand.clear({ brand: 'brand_1' }) ``` **CLI** ```bash npx startup-builder do Brand.clear --json '{"brand":"brand_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Brand.clear({ brand: 'brand_1' })" } } ``` ## Example One Brand can cover two Startups with different [Customers](/business/nouns/customer). One Startup can sell an Offer under a second Brand for a new audience. # Budget URL: /business/nouns/budget · Id: `noun:budget` > A Budget is the amount a Startup plans to spend or earn on one account in one Period, read against actual Entries. A Budget is the amount a [Startup](/business/nouns/startup) plans to spend or earn on one account in one [Period](/business/nouns/period), read against actual [Entries](/business/nouns/entry). ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `account` | `string` | Yes | The chart-of-accounts code it plans, such as `expense.ads`. | | `period` | [Period](/business/nouns/period) | Yes | The Period it plans. | | `amount` | `money` | Yes | The amount set for the account in the Period. | | `actual` | `money` | No | What the Entries in the Period add up to so far. | ## Object ```json { "$id": "https://api.sb/patentpad.com/budgets/budget_1", "$type": "Budget", "account": "expense.ads", "period": "period_1", "amount": { "amount": 499, "currency": "USD" }, "actual": { "amount": 499, "currency": "USD" } } ``` ## Relationships - A Budget **plans** one [Period](/business/nouns/period): a Budget plans one [Period](/business/nouns/period), read beside the actual [Entries](/business/nouns/entry) that fall in it. `plans`, inverse [`budgets`](/business/nouns/period#rel-budgets). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Budget.create](/business/nouns/budget/create) | Creates a Budget. Inherited from [Noun](/business/nouns/noun). | None. | `Budget.created` | Two-way: `try`, `send`, `do` | | [Budget.get](/business/nouns/budget/get) | Returns one Budget by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Budget.list](/business/nouns/budget/list) | Returns Budgets, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Budget.update](/business/nouns/budget/update) | Changes the given properties of a Budget. Inherited from [Noun](/business/nouns/noun). | None. | `Budget.updated` | Two-way: `try`, `send`, `do` | | [Budget.delete](/business/nouns/budget/delete) | Deletes a Budget; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Budget.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Budget.create` | Yes | Yes | Yes | No | | `Budget.get` | Yes | Yes | Yes | Yes | | `Budget.list` | Yes | Yes | Yes | Yes | | `Budget.update` | Yes | Yes | Yes | No | | `Budget.delete` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Add a budget to ShiftNote with a period. ``` **API** ```bash curl -X POST https://api.sb/shiftnote.app/budgets \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"account":"expense.ads","period":"period_1","amount":{"amount":79,"currency":"USD"}}' ``` ```json { "api": "https://api.sb/shiftnote.app", "budget": { "$id": "https://api.sb/shiftnote.app/budgets/budget_1", "$type": "Budget", "account": "expense.ads", "period": "period_1", "amount": { "amount": 79, "currency": "USD" } }, "action": { "$id": "https://api.sb/shiftnote.app/actions/action_1", "operation": "Budget.create", "status": "done" }, "links": { "self": "https://api.sb/shiftnote.app/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const budget = await $.Budget.create({ account: 'expense.ads', period: 'period_1', amount: { amount: 79, currency: 'USD' } }) ``` **CLI** ```bash npx startup-builder do Budget.create --json '{"account":"expense.ads","period":"period_1","amount":{"amount":79,"currency":"USD"}}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Budget.create({ account: 'expense.ads', period: 'period_1', amount: { amount: 79, currency: 'USD' } })" } } ``` ## Example A tutoring marketplace sets a $4,000 Budget on `expense.ads` for one month. By the 18th its [Entries](/business/nouns/entry) add up to $3,100, so `actual` reads $3,100 and the remaining $900 bounds the month's ad spend. # Builder URL: /business/nouns/builder · Id: `noun:builder` > A Builder is a named part of api.sb that builds one side of a Startup; StartupBuilder directs SiteBuilder, SoftwareBuilder, ServiceBuilder, and SalesBuilder. A Builder is a named part of [api.sb](/code/platform/api-sb) that builds one side of a [Startup](/business/nouns/startup); [StartupBuilder](/code/builders/startup) directs [SiteBuilder](/code/builders/site), [SoftwareBuilder](/code/builders/software), [ServiceBuilder](/code/builders/service), and [SalesBuilder](/code/builders/sales). ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `name` | `string` | Yes | One of `StartupBuilder`, `SiteBuilder`, `SoftwareBuilder`, `ServiceBuilder`, or `SalesBuilder`. | ## Object ```json { "$id": "https://api.sb/patentpad.com/builders/builder_1", "$type": "Builder", "name": "StartupBuilder" } ``` ## Relationships - A Builder **builds** many [Startups](/business/nouns/startup): [StartupBuilder](/code/builders/startup) directs [SiteBuilder](/code/builders/site), [SoftwareBuilder](/code/builders/software), [ServiceBuilder](/code/builders/service) and [SalesBuilder](/code/builders/sales), each building one side of a [Startup](/business/nouns/startup). `builds`, inverse [`builtWith`](/business/nouns/startup#rel-built-with). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Builder.get](/business/nouns/builder/get) | Returns one Builder by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Builder.list](/business/nouns/builder/list) | Returns Builders, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | A Builder is kept forever and never edited: it has no `update` or `delete`. ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Builder.get` | Yes | Yes | Yes | Yes | | `Builder.list` | Yes | Yes | Yes | Yes | ## Call it **Ask** ```text Show me the latest builder. ``` **API** ```bash curl https://api.sb/shiftnote.app/builders/builder_1 \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/shiftnote.app", "$type": "Builder", "$id": "https://api.sb/shiftnote.app/builders/builder_1", "builder": { "$id": "https://api.sb/shiftnote.app/builders/builder_1", "$type": "Builder", "name": "StartupBuilder" }, "links": { "self": "https://api.sb/shiftnote.app/builders/builder_1", "up": "https://api.sb/shiftnote.app/builders" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const builder = await $.Builder.get({ id: 'builder_1' }) ``` **CLI** ```bash npx startup-builder do Builder.get --json '{"id":"builder_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Builder.get({ id: 'builder_1' })" } } ``` ## Example A Startup sells certified translations of official documents. SiteBuilder publishes its order [Page](/business/nouns/page), SoftwareBuilder ships the drafting [Agent](/business/nouns/agent), ServiceBuilder credentials the translators, and SalesBuilder runs its per-page [Offers](/business/nouns/offer). StartupBuilder moves it from Building to Live. # Campaign URL: /business/nouns/campaign · Id: `noun:campaign` > A Campaign is a bounded effort toward a Goal, with a budget, a window, and the Ads or Messages it sends to Audiences. A Campaign is a bounded effort toward a [Goal](/business/nouns/goal), with a budget, a window, and the [Ads](/business/nouns/ad) or [Messages](/business/nouns/message) it sends to [Audiences](/business/nouns/audience). ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `budget` | `money` | No | What it may spend. | | `startsAt` | `datetime` | No | When it starts. | | `endsAt` | `datetime` | No | When it ends. | ## Object ```json { "$id": "https://api.sb/tutorloop.com/campaigns/campaign_1", "$type": "Campaign", "budget": { "amount": 60, "currency": "USD" }, "startsAt": "2026-10-22T12:00:00Z", "endsAt": "2026-10-22T12:00:00Z" } ``` ## Relationships - A Campaign **advances** one [Goal](/business/nouns/goal): a Campaign spends its budget and window toward one [Goal](/business/nouns/goal). `advances`, inverse [`advancedBy`](/business/nouns/goal#rel-advanced-by). - A Campaign **runs** many [Ads](/business/nouns/ad): a Campaign places [Ads](/business/nouns/ad) that share its budget and window. `runs`, inverse [`runIn`](/business/nouns/ad#rel-run-in). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Campaign.create](/business/nouns/campaign/create) | Creates a Campaign. Inherited from [Noun](/business/nouns/noun). | None. | `Campaign.created` | Two-way: `try`, `send`, `do` | | [Campaign.get](/business/nouns/campaign/get) | Returns one Campaign by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Campaign.list](/business/nouns/campaign/list) | Returns Campaigns, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Campaign.update](/business/nouns/campaign/update) | Changes the given properties of a Campaign. Inherited from [Noun](/business/nouns/noun). | None. | `Campaign.updated` | Two-way: `try`, `send`, `do` | | [Campaign.delete](/business/nouns/campaign/delete) | Deletes a Campaign; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Campaign.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Campaign.create` | Yes | Yes | Yes | No | | `Campaign.get` | Yes | Yes | Yes | Yes | | `Campaign.list` | Yes | Yes | Yes | Yes | | `Campaign.update` | Yes | Yes | Yes | No | | `Campaign.delete` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Add a campaign to QuietCopy. ``` **API** ```bash curl -X POST https://api.sb/quietcopy.com/campaigns \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"budget":{"amount":39,"currency":"USD"}}' ``` ```json { "api": "https://api.sb/quietcopy.com", "campaign": { "$id": "https://api.sb/quietcopy.com/campaigns/campaign_1", "$type": "Campaign", "budget": { "amount": 39, "currency": "USD" }, "startsAt": "2026-10-22T12:00:00Z" }, "action": { "$id": "https://api.sb/quietcopy.com/actions/action_1", "operation": "Campaign.create", "status": "done" }, "links": { "self": "https://api.sb/quietcopy.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const campaign = await $.Campaign.create({ budget: { amount: 39, currency: 'USD' } }) ``` **CLI** ```bash npx startup-builder do Campaign.create --json '{"budget":{"amount":39,"currency":"USD"}}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Campaign.create({ budget: { amount: 39, currency: 'USD' } })" } } ``` ## Example A three-week Campaign for a dropship store of espresso-machine filters spends $1,500 on short-video [Ads](/business/nouns/ad). Its [Goal](/business/nouns/goal) is 120 first [Orders](/business/nouns/order), and it ends on day 21 even if the Goal falls short. # Candidate URL: /business/nouns/candidate · Id: `noun:candidate` > A Candidate is a Person under consideration for an Opening, with the graded Evidence for and against them. A Candidate is a [Person](/business/nouns/person) under consideration for an [Opening](/business/nouns/opening), with the graded [Evidence](/business/nouns/evidence) for and against them. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `opening` | [Opening](/business/nouns/opening) | Yes | The Opening the Person is considered for. | | `person` | [Person](/business/nouns/person) | Yes | The Person, whose record crosses Startups only with Consent. | | `source` | `string` | Yes | One of `pool`, `prospecting`, `listing`, or `referral`. | | `state` | `string` | Yes | One of `screening`, `tryout`, `proposed`, `hired`, or `declined`. | | `delta` | `json` | No | The per-Verb difference between the Candidate and the incumbent Agent in the tryout. | ## Object ```json { "$id": "https://api.sb/ledgerlark.com/candidates/candidate_1", "$type": "Candidate", "opening": "opening_1", "person": "person_1", "source": "pool", "state": "screening", "delta": {} } ``` ## Relationships - A Candidate **applies to** one [Opening](/business/nouns/opening): Candidates for an [Opening](/business/nouns/opening) are screened only on what its [Hypothesis](/business/nouns/hypothesis) still lacks. `appliesTo`, inverse [`candidates`](/business/nouns/opening#rel-candidates). - A Candidate **presents** one [Person](/business/nouns/person): a Candidate is one [Person](/business/nouns/person)’s candidacy; the Person’s record crosses [Startups](/business/nouns/startup) only with [Consent](/business/nouns/consent). `presents`, inverse [`candidacies`](/business/nouns/person#rel-candidacies). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Candidate.screen](/business/nouns/candidate/screen) | Screen asks a Candidate only what the Opening’s Hypothesis still lacks, in writing, and grades each answer as Evidence. | [Recruiter](/agents/people/recruiter) | [`Candidate.screened`](/business/events/Candidate.screened) | None. | | [Candidate.create](/business/nouns/candidate/create) | Creates a Candidate. Inherited from [Noun](/business/nouns/noun). | None. | `Candidate.created` | Two-way: `try`, `send`, `do` | | [Candidate.get](/business/nouns/candidate/get) | Returns one Candidate by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Candidate.list](/business/nouns/candidate/list) | Returns Candidates, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Candidate.update](/business/nouns/candidate/update) | Changes the given properties of a Candidate. Inherited from [Noun](/business/nouns/noun). | None. | `Candidate.updated` | Two-way: `try`, `send`, `do` | | [Candidate.delete](/business/nouns/candidate/delete) | Deletes a Candidate; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Candidate.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Candidate.create` | Yes | Yes | Yes | No | | `Candidate.get` | Yes | Yes | Yes | Yes | | `Candidate.list` | Yes | Yes | Yes | Yes | | `Candidate.update` | Yes | Yes | Yes | No | | `Candidate.delete` | Yes | Yes | Yes | No | | `Candidate.screen` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Screen the candidate Rosa Ibarra. ``` **API** ```bash curl -X POST https://api.sb/patentpad.com/candidates/candidate_1/screen \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/patentpad.com", "candidate": { "$id": "https://api.sb/patentpad.com/candidates/candidate_1", "$type": "Candidate", "opening": "opening_1", "person": "person_1", "source": "pool", "state": "screening" }, "action": { "$id": "https://api.sb/patentpad.com/actions/action_1", "operation": "Candidate.screen", "status": "done" }, "links": { "self": "https://api.sb/patentpad.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const candidate = await $.Candidate.screen({ candidate: 'candidate_1' }) ``` **CLI** ```bash npx startup-builder do Candidate.screen --json '{"candidate":"candidate_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Candidate.screen({ candidate: 'candidate_1' })" } } ``` ## Example A Candidate for a `cofounder` Opening at a clinic-scheduling API arrives from the talent pool with shipped work from a past [Startup](/business/nouns/startup). Her tryout closes three clinic-group deals the [Sales Lead](/agents/sales/sales-lead) [Agent](/business/nouns/agent) had stalled on, so her state moves to `proposed`. # screen URL: /business/nouns/candidate/screen · Id: `verb:Candidate.screen` · Call: `await $.Candidate.screen({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Screen asks a Candidate only what the Opening’s Hypothesis still lacks, in writing, and grades each answer as Evidence. Screen asks a [Candidate](/business/nouns/candidate) only what the [Opening](/business/nouns/opening)’s [Hypothesis](/business/nouns/hypothesis) still lacks, in writing, and grades each answer as [Evidence](/business/nouns/evidence). ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `candidate` | [Candidate](/business/nouns/candidate) | Yes | The Candidate to screen. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `candidate` | [Candidate](/business/nouns/candidate) | Yes | The Candidate, with graded Evidence attached. | ## Effects - Emits [`Candidate.screened`](/business/events/Candidate.screened). - Performed by the [Recruiter](/agents/people/recruiter). - Gives self-description and unsupported praise zero weight. - Moves a passing Candidate to `tryout`. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Candidate.screen](/business/nouns/candidate/screen) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Screen the candidate Rosa Ibarra. ``` **API** ```bash curl -X POST https://api.sb/patentpad.com/candidates/candidate_1/screen \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/patentpad.com", "candidate": { "$id": "https://api.sb/patentpad.com/candidates/candidate_1", "$type": "Candidate", "opening": "opening_1", "person": "person_1", "source": "pool", "state": "screening" }, "action": { "$id": "https://api.sb/patentpad.com/actions/action_1", "operation": "Candidate.screen", "status": "done" }, "links": { "self": "https://api.sb/patentpad.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const candidate = await $.Candidate.screen({ candidate: 'candidate_1' }) ``` **CLI** ```bash npx startup-builder do Candidate.screen --json '{"candidate":"candidate_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Candidate.screen({ candidate: 'candidate_1' })" } } ``` # Capability URL: /business/nouns/capability · Id: `noun:capability` > A Capability is a named set of Verbs on one Noun family that every Startup reaches through api.sb with one key, metered, limited, and logged. A Capability is a named set of [Verbs](/business/nouns/verb) on one [Noun](/business/nouns/noun) family that every [Startup](/business/nouns/startup) reaches through [api.sb](/code/platform/api-sb) with one key, metered, limited, and logged. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `name` | `string` | Yes | The name, such as `Workflows` or `Search`. | | `nouns` | list of [Noun](/business/nouns/noun) | Yes | The Nouns it exposes, each with its Verbs. | | `modes` | `json` | No | The Mode each Verb accepts; a stateless Verb is `try` only. | | `upstream` | `string` | No | Who performs it behind api.sb, held as data and swappable without a caller noticing. | ## Object ```json { "$id": "https://api.sb/quietcopy.com/capabilities/capability_1", "$type": "Capability", "name": "QuietCopy", "nouns": [ "noun_1" ], "modes": {}, "upstream": "Example upstream" } ``` ## Relationships - A Capability **exposes** many [Nouns](/business/nouns/noun): a Capability exposes [Verbs](/business/nouns/verb) on one [Noun](/business/nouns/noun) family, metered, limited and logged under one key. `exposes`, inverse [`exposedBy`](/business/nouns/noun#rel-exposed-by). - A Capability **has** many [Recovery Objectives](/business/nouns/recovery-objective): the Capability the objective restores. `recoveryObjectives`, inverse [`capability`](/business/nouns/recovery-objective#rel-capability). - A Capability **runs** many [Systems](/business/nouns/system): a [System](/business/nouns/system) is built on Capabilities, such as [Workflows](/business/nouns/workflow) or Search, that every [Startup](/business/nouns/startup) reaches with one key. `runs`, inverse [`runsOn`](/business/nouns/system#rel-runs-on). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Capability.get](/business/nouns/capability/get) | Returns one Capability by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Capability.list](/business/nouns/capability/list) | Returns Capabilities, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | A Capability is kept forever and never edited: it has no `update` or `delete`. ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Capability.get` | Yes | Yes | Yes | Yes | | `Capability.list` | Yes | Yes | Yes | Yes | ## Call it **Ask** ```text Show me the latest capability. ``` **API** ```bash curl https://api.sb/petpantry.shop/capabilities/capability_1 \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/petpantry.shop", "$type": "Capability", "$id": "https://api.sb/petpantry.shop/capabilities/capability_1", "capability": { "$id": "https://api.sb/petpantry.shop/capabilities/capability_1", "$type": "Capability", "name": "PetPantry", "nouns": [ "noun_1" ] }, "links": { "self": "https://api.sb/petpantry.shop/capabilities/capability_1", "up": "https://api.sb/petpantry.shop/capabilities" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const capability = await $.Capability.get({ id: 'capability_1' }) ``` **CLI** ```bash npx startup-builder do Capability.get --json '{"id":"capability_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Capability.get({ id: 'capability_1' })" } } ``` ## Example A clinic-reminder [SaaS](/products/templates/saas) sends 9,000 text reminders a day through the messaging Capability. It uses the key it uses for payments and search, every send is metered, and its [Limit](/business/nouns/limit) stops sends past 12,000 a day. # Card URL: /business/nouns/card · Id: `noun:card` > A Card is a payment credential a Startup issues to one Worker under one Mandate, with controls compiled from that Mandate. A Card is a payment credential a [Startup](/business/nouns/startup) issues to one [Worker](/business/nouns/worker) under one [Mandate](/business/nouns/mandate), with controls compiled from that Mandate. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `form` | `string` | Yes | `singleUse` pays one Task and closes; `merchant` pays one merchant until the Mandate ends; `physical` is for a Human only. | | `status` | `string` | Yes | Follows its Mandate: frozen while the Mandate is paused, closed once it is revoked or a single-use Card has paid. | | `merchants` | `string[]` | No | The merchants or merchant categories it may pay, compiled from the Mandate. | | `limit` | [Limit](/business/nouns/limit) | Yes | The amount per charge and per period; every interval is set, so the rail’s default never decides. | | `task` | [Task](/business/nouns/task) | No | For a `singleUse` Card: the Task it pays for, which also holds the receipt. | | `last4` | `string` | No | The last four digits; the full number never leaves the rail. | ## Object ```json { "$id": "https://api.sb/quietcopy.com/cards/card_1", "$type": "Card", "form": "singleUse", "status": "active", "merchants": [ "advertising" ], "limit": "limit_1", "task": "task_1", "last4": "4242" } ``` ## Relationships - A Card **is carried by** one [Worker](/business/nouns/worker): a [Worker](/business/nouns/worker) carries the Cards issued for its [Mandates](/business/nouns/mandate); the cardholder on the rail is always the [Company](/business/nouns/company). `carriedBy`, inverse [`carries`](/business/nouns/worker#rel-carries). - A Card **is funded by** one [Mandate](/business/nouns/mandate): a [Mandate](/business/nouns/mandate) funds the Cards that spend under it; pausing it freezes them and revoking it closes them. `fundedBy`, inverse [`funds`](/business/nouns/mandate#rel-funds). ## Lifecycle | State | Meaning | Moves to | | --- | --- | --- | | `active` (first) | It pays the merchants its Mandate allows, within its Limit. | `frozen` on [`Mandate.paused`](/business/events/Mandate.paused) when the Mandate is this Card’s; `closed` on [`Mandate.revoked`](/business/events/Mandate.revoked) when the Mandate is this Card’s; `closed` on [`Mandate.spent`](/business/events/Mandate.spent) when this Card is single-use and paid its Task | | `frozen` | Its Mandate is paused, so every charge is declined. | `active` on [`Mandate.resumed`](/business/events/Mandate.resumed) when the Mandate is this Card’s; `closed` on [`Mandate.revoked`](/business/events/Mandate.revoked) when the Mandate is this Card’s | | `closed` | Its Mandate is revoked or its single use is spent; the record and its charges stay. | None: it ends here. | ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Card.issue](/business/nouns/card/issue) | Issue creates a Card under a Mandate once the Mandate check passes, with explicit limits on every interval. | [Treasurer](/agents/finance/treasurer) | [`Card.issued`](/business/events/Card.issued) | Two-way: `try`, `send`, `do` | | [Card.get](/business/nouns/card/get) | Returns one Card by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Card.list](/business/nouns/card/list) | Returns Cards, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | A Card is kept forever and never edited: it has no `update` or `delete`. ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Card.get` | Yes | Yes | Yes | Yes | | `Card.list` | Yes | Yes | Yes | Yes | | `Card.issue` | Yes | Yes | Yes | No | ## Stripe **Issuing Card** (`issuing.card`). The source of truth is db.sb, and Stripe holds a copy written from it. | Property | Stripe field | Source of truth | | --- | --- | --- | | `status` | `status` | db.sb | | `limit` | `spending_controls.spending_limits[]` | db.sb | | `merchants` | `spending_controls.allowed_categories` | db.sb | | `last4` | `last4` | Stripe | ## Call it **Ask** ```text Issue the latest card with a mandate. ``` **API** ```bash curl -X POST https://api.sb/ledgerlark.com/cards/issue \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"mandate":"mandate_1","form":"singleUse"}' ``` ```json { "api": "https://api.sb/ledgerlark.com", "card": { "$id": "https://api.sb/ledgerlark.com/cards/card_1", "$type": "Card", "form": "singleUse", "status": "active", "limit": "limit_1" }, "action": { "$id": "https://api.sb/ledgerlark.com/actions/action_1", "operation": "Card.issue", "status": "done" }, "links": { "self": "https://api.sb/ledgerlark.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const card = await $.Card.issue({ mandate: 'mandate_1', form: 'singleUse' }) ``` **CLI** ```bash npx startup-builder do Card.issue --json '{"mandate":"mandate_1","form":"singleUse"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Card.issue({ mandate: 'mandate_1', form: 'singleUse' })" } } ``` ## Example The [Marketing Lead](/agents/marketing/marketing-lead) [Agent](/business/nouns/agent) at a sleep-tracking app holds two Cards under one Mandate. One is a `merchant` Card for its ad network at $2,000 a month; the other is a `singleUse` Card for a $450 design tool. Pausing the Mandate freezes both at once. # issue URL: /business/nouns/card/issue · Id: `verb:Card.issue` · Call: `await $.Card.issue({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Issue creates a Card under a Mandate once the Mandate check passes, with explicit limits on every interval. [Issue](/business/nouns/issue) creates a [Card](/business/nouns/card) under a [Mandate](/business/nouns/mandate) once the Mandate check passes, with explicit limits on every interval. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `mandate` | [Mandate](/business/nouns/mandate) | Yes | The Mandate the Card spends under. | | `form` | `string` | Yes | Which kind of Card to issue. | | `task` | [Task](/business/nouns/task) | No | For a `singleUse` Card: the Task it pays for. | | `merchant` | `string` | No | For a `merchant` Card: the one merchant it may pay. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `card` | [Card](/business/nouns/card) | Yes | The active Card, with its last four digits and limits. | ## Effects - Emits [`Card.issued`](/business/events/Card.issued). - Performed by the [Treasurer](/agents/finance/treasurer). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Refuses `card-program-pending` while the card program of the Startup’s owner of record awaits its grant. - A `singleUse` Card closes after its one charge. - Each charge runs the Mandate check in real time and declines on its Limit or a `hold` spend state. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Card.issue](/business/nouns/card/issue) | | The card program of the Startup’s owner of record awaits its grant, so no Card can be issued. | [`card-program-pending`](/code/api/errors/card-program-pending) | Call again once the program is granted; nothing on the Startup’s side changes. | [Card.issue](/business/nouns/card/issue) | | `card-program-pending` while the card program of the Startup’s owner of record awaits its grant | [`card-program-pending`](/code/api/errors/card-program-pending) | Clear what the check names, then call it again. | [Card.issue](/business/nouns/card/issue) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Issue the latest card with a mandate. ``` **API** ```bash curl -X POST https://api.sb/ledgerlark.com/cards/issue \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"mandate":"mandate_1","form":"singleUse"}' ``` ```json { "api": "https://api.sb/ledgerlark.com", "card": { "$id": "https://api.sb/ledgerlark.com/cards/card_1", "$type": "Card", "form": "singleUse", "status": "active", "limit": "limit_1" }, "action": { "$id": "https://api.sb/ledgerlark.com/actions/action_1", "operation": "Card.issue", "status": "done" }, "links": { "self": "https://api.sb/ledgerlark.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const card = await $.Card.issue({ mandate: 'mandate_1', form: 'singleUse' }) ``` **CLI** ```bash npx startup-builder do Card.issue --json '{"mandate":"mandate_1","form":"singleUse"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Card.issue({ mandate: 'mandate_1', form: 'singleUse' })" } } ``` Guides that call it: [Issue a card with a limit](/systems/finance/issue-a-card-with-a-limit). # Change URL: /business/nouns/change · Id: `noun:change` > A Change is a proposed set of writes to definitions, previewed on its own branch, checked, approved, and merged as one unit. A Change is a proposed set of writes to definitions, previewed on its own branch, checked, approved, and merged as one unit. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `status` | `string` | Yes | One of `Open`, `Reviewing`, `Merged`, or `Closed`. | | `base` | [Version](/business/nouns/version) | Yes | The Version it was drafted against. | | `tier` | `integer` | No | Launch tier from the merged diff: 3 fixes, 2 adds a Verb or Entitlement, 1 adds a Product or Offer. | ## Object ```json { "$id": "https://api.sb/petpantry.shop/changes/change_1", "$type": "Change", "status": "Open", "base": "version_1", "tier": 1 } ``` ## Relationships - A Change **implements decision** one [Decision](/business/nouns/decision): every merged Change traces back to the [Decision](/business/nouns/decision) that authorized it. `implementsDecision`, inverse [`changes`](/business/nouns/decision#rel-changes). - A Change **resolves** many [Issues](/business/nouns/issue): a Change names the [Issues](/business/nouns/issue) it fixes; each resolves when the last open Change naming it reaches all traffic. `resolves`, inverse [`resolvedBy`](/business/nouns/issue#rel-resolved-by). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Change.merge](/business/nouns/change/merge) | Merge applies a Change to live data with a three-way, field-level merge against its base Version. | [Engineering Lead](/agents/engineering/engineering-lead) | [`Change.merged`](/business/events/Change.merged) | None. | | [Change.revert](/business/nouns/change/revert) | Revert undoes a merged Change with a new Change and a superseding Decision, deleting nothing. | [Engineering Lead](/agents/engineering/engineering-lead) | [`Change.reverted`](/business/events/Change.reverted) | None. | | [Change.review](/business/nouns/change/review) | Review runs every Evaluator on a Change’s preview and records each verdict on the Change. | [Quality Lead](/agents/quality/quality-lead) | [`Change.reviewed`](/business/events/Change.reviewed) | None. | | [Change.create](/business/nouns/change/create) | Creates a Change. Inherited from [Noun](/business/nouns/noun). | None. | `Change.created` | Two-way: `try`, `send`, `do` | | [Change.get](/business/nouns/change/get) | Returns one Change by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Change.list](/business/nouns/change/list) | Returns Changes, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | A Change is kept forever and never edited: it has no `update` or `delete`. ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Change.create` | Yes | Yes | Yes | No | | `Change.get` | Yes | Yes | Yes | Yes | | `Change.list` | Yes | Yes | Yes | Yes | | `Change.merge` | Yes | Yes | Yes | No | | `Change.revert` | Yes | Yes | Yes | No | | `Change.review` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Review the latest change. ``` **API** ```bash curl -X POST https://api.sb/petpantry.shop/changes/change_1/review \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/petpantry.shop", "change": { "$id": "https://api.sb/petpantry.shop/changes/change_1", "$type": "Change", "status": "Open", "base": "version_1" }, "action": { "$id": "https://api.sb/petpantry.shop/actions/action_1", "operation": "Change.review", "status": "done" }, "links": { "self": "https://api.sb/petpantry.shop/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const change = await $.Change.review({ change: 'change_1' }) ``` **CLI** ```bash npx startup-builder do Change.review --json '{"change":"change_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Change.review({ change: 'change_1' })" } } ``` ## Example A Change adds a `languages` field to the [Supplier](/business/nouns/supplier) [Noun](/business/nouns/noun) of a translation marketplace. It previews on its own branch, passes its checks, and merges with one [Approval](/business/nouns/approval). # merge URL: /business/nouns/change/merge · Id: `verb:Change.merge` · Call: `await $.Change.merge({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Merge applies a Change to live data with a three-way, field-level merge against its base Version. Merge applies a [Change](/business/nouns/change) to live data with a three-way, field-level merge against its base [Version](/business/nouns/version). ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `change` | [Change](/business/nouns/change) | Yes | The reviewed Change. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `version` | [Version](/business/nouns/version) | Yes | The new Version. | | `change` | [Change](/business/nouns/change) | Yes | The Change, now merged into live data. | ## Effects - Emits [`Change.merged`](/business/events/Change.merged). - Performed by the [Engineering Lead](/agents/engineering/engineering-lead). - Sends the Change back to review when a field changed on both sides since its base. - Never overwrites a concurrent edit. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Change.merge](/business/nouns/change/merge) | | The record changed since it was read, so the write would overwrite a newer version. | [`conflict`](/code/api/errors/conflict) | Read the record again, then retry the write against its current state. | [Change.merge](/business/nouns/change/merge) | | The record is not in a state that allows this Verb, so the call is refused. | [`refused`](/code/api/errors/refused) | Read the record, run the Verb that moves it to an allowed state, then retry. | [Change.merge](/business/nouns/change/merge) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Merge the latest change. ``` **API** ```bash curl -X POST https://api.sb/tutorloop.com/changes/change_1/merge \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/tutorloop.com", "version": { "$id": "https://api.sb/tutorloop.com/versions/version_1", "$type": "Version", "fingerprint": "sha256:9f2c4e1a7b3d" }, "change": { "$id": "https://api.sb/tutorloop.com/changes/change_1", "$type": "Change", "status": "Merged", "base": "version_1" }, "action": { "$id": "https://api.sb/tutorloop.com/actions/action_1", "operation": "Change.merge", "status": "done" }, "links": { "self": "https://api.sb/tutorloop.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { version, change } = await $.Change.merge({ change: 'change_1' }) ``` **CLI** ```bash npx startup-builder do Change.merge --json '{"change":"change_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Change.merge({ change: 'change_1' })" } } ``` Next: [`Version.deploy`](/business/nouns/version/deploy) (in `guide:ship-my-changes`). Guides that call it: [Ship my changes](/code/ship-my-changes). # revert URL: /business/nouns/change/revert · Id: `verb:Change.revert` · Call: `await $.Change.revert({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Revert undoes a merged Change with a new Change and a superseding Decision, deleting nothing. Revert undoes a merged [Change](/business/nouns/change) with a new Change and a superseding [Decision](/business/nouns/decision), deleting nothing. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `change` | [Change](/business/nouns/change) | Yes | The merged Change to undo. | | `reason` | `text` | Yes | Why it is undone. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `revert` | [Change](/business/nouns/change) | Yes | The Change that undoes it. | ## Effects - Emits [`Change.reverted`](/business/events/Change.reverted). - Performed by the [Engineering Lead](/agents/engineering/engineering-lead). - Supersedes the Decision that caused the original Change. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Change.revert](/business/nouns/change/revert) | | The record is not in a state that allows this Verb, so the call is refused. | [`refused`](/code/api/errors/refused) | Read the record, run the Verb that moves it to an allowed state, then retry. | [Change.revert](/business/nouns/change/revert) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Revert the latest change. ``` **API** ```bash curl -X POST https://api.sb/quietcopy.com/changes/change_1/revert \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"reason":"Example reason"}' ``` ```json { "api": "https://api.sb/quietcopy.com", "revert": { "$id": "https://api.sb/quietcopy.com/changes/change_1", "$type": "Change", "status": "Open", "base": "version_1" }, "action": { "$id": "https://api.sb/quietcopy.com/actions/action_1", "operation": "Change.revert", "status": "done" }, "links": { "self": "https://api.sb/quietcopy.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const revert = await $.Change.revert({ change: 'change_1', reason: 'Example reason' }) ``` **CLI** ```bash npx startup-builder do Change.revert --json '{"change":"change_1","reason":"Example reason"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Change.revert({ change: 'change_1', reason: 'Example reason' })" } } ``` # review URL: /business/nouns/change/review · Id: `verb:Change.review` · Call: `await $.Change.review({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Review runs every Evaluator on a Change’s preview and records each verdict on the Change. Review runs every [Evaluator](/business/nouns/evaluator) on a [Change](/business/nouns/change)’s preview and records each verdict on the Change. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `change` | [Change](/business/nouns/change) | Yes | The open Change. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `change` | [Change](/business/nouns/change) | Yes | The Change with its verdicts. | ## Effects - Emits [`Change.reviewed`](/business/events/Change.reviewed). - Performed by the [Quality Lead](/agents/quality/quality-lead). - Opens an Approval when the Change’s stakes exceed the Startup’s threshold. - Moves each Issue the Change resolves to in progress. - Waits for each Integration-bound Evaluator’s outside run on the head and records its result as a verdict. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Change.review](/business/nouns/change/review) | | The record is not in a state that allows this Verb, so the call is refused. | [`refused`](/code/api/errors/refused) | Read the record, run the Verb that moves it to an allowed state, then retry. | [Change.review](/business/nouns/change/review) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Review the latest change. ``` **API** ```bash curl -X POST https://api.sb/petpantry.shop/changes/change_1/review \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/petpantry.shop", "change": { "$id": "https://api.sb/petpantry.shop/changes/change_1", "$type": "Change", "status": "Open", "base": "version_1" }, "action": { "$id": "https://api.sb/petpantry.shop/actions/action_1", "operation": "Change.review", "status": "done" }, "links": { "self": "https://api.sb/petpantry.shop/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const change = await $.Change.review({ change: 'change_1' }) ``` **CLI** ```bash npx startup-builder do Change.review --json '{"change":"change_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Change.review({ change: 'change_1' })" } } ``` Next: [`Change.merge`](/business/nouns/change/merge) (in `guide:ship-my-changes`). Guides that call it: [Ship my changes](/code/ship-my-changes). # Channel URL: /business/nouns/channel · Id: `noun:channel` > A Channel is a place Messages flow, such as a chat channel, a Mailbox, or an SMS number. A Channel is a place [Messages](/business/nouns/message) flow, such as a chat channel, a [Mailbox](/business/nouns/mailbox), or an SMS number. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `medium` | `string` | Yes | The platform type, such as `email`, `sms`, or `chat`. | | `organization` | [Organization](/business/nouns/organization) | No | The outside Organization the Channel is shared with; its new Messages open Conversations for that Customer. | | `external` | `boolean` | No | True when people from another Organization post in it, as in a channel two companies share. | | `areaCode` | `string` | No | For an `sms` Channel, the phone area code its number is drawn from, such as `512`. | | `number` | `string` | No | For an `sms` Channel, its phone number in international form, assigned when it is created. | ## Object ```json { "$id": "https://api.sb/routewise.dev/channels/channel_1", "$type": "Channel", "medium": "email", "organization": "organization_1", "external": true, "areaCode": "Example area code", "number": "Example number" } ``` ## Relationships - A Channel **hosts** many [Threads](/business/nouns/thread): a Channel holds [Threads](/business/nouns/thread). `hosts`, inverse [`hostedIn`](/business/nouns/thread#rel-hosted-in). - A Channel **has** many [Messages](/business/nouns/message): every [Message](/business/nouns/message) flows through one Channel. `messages`, inverse [`postedIn`](/business/nouns/message#rel-posted-in). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Channel.create](/business/nouns/channel/create) | Creates a Channel. Inherited from [Noun](/business/nouns/noun). | None. | `Channel.created` | Two-way: `try`, `send`, `do` | | [Channel.get](/business/nouns/channel/get) | Returns one Channel by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Channel.list](/business/nouns/channel/list) | Returns Channels, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Channel.update](/business/nouns/channel/update) | Changes the given properties of a Channel. Inherited from [Noun](/business/nouns/noun). | None. | `Channel.updated` | Two-way: `try`, `send`, `do` | | [Channel.delete](/business/nouns/channel/delete) | Deletes a Channel; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Channel.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Channel.create` | Yes | Yes | Yes | No | | `Channel.get` | Yes | Yes | Yes | Yes | | `Channel.list` | Yes | Yes | Yes | Yes | | `Channel.update` | Yes | Yes | Yes | No | | `Channel.delete` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Add a channel to LedgerLark. ``` **API** ```bash curl -X POST https://api.sb/ledgerlark.com/channels \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"medium":"email"}' ``` ```json { "api": "https://api.sb/ledgerlark.com", "channel": { "$id": "https://api.sb/ledgerlark.com/channels/channel_1", "$type": "Channel", "medium": "email" }, "action": { "$id": "https://api.sb/ledgerlark.com/actions/action_1", "operation": "Channel.create", "status": "done" }, "links": { "self": "https://api.sb/ledgerlark.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const channel = await $.Channel.create({ medium: 'email' }) ``` **CLI** ```bash npx startup-builder do Channel.create --json '{"medium":"email"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Channel.create({ medium: 'email' })" } } ``` ## Example A tutoring marketplace runs three Channels: the `help@` [Mailbox](/business/nouns/mailbox), one chat channel per family and its tutor, and an SMS number for session reminders. # Cohort URL: /business/nouns/cohort · Id: `noun:cohort` > A Cohort is a set of Startups that receives one Version of a shared definition, or one step of a Play, at the same time. A Cohort is a set of [Startups](/business/nouns/startup) that receives one [Version](/business/nouns/version) of a shared definition, or one step of a [Play](/business/nouns/play), at the same time. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `query` | `json` | Yes | The Portfolio query that selects its Startups. | | `control` | `boolean` | No | True when the Cohort stays on the prior Version as the control. | ## Object ```json { "$id": "https://api.sb/patentpad.com/cohorts/cohort_1", "$type": "Cohort", "query": {}, "control": true } ``` ## Relationships - A Cohort **is drawn from** one [Portfolio](/business/nouns/portfolio): a Cohort selects its [Startups](/business/nouns/startup) from one [Portfolio](/business/nouns/portfolio) by a saved query. `drawnFrom`, inverse [`cohorts`](/business/nouns/portfolio#rel-cohorts). - A Cohort **is pinned to** one [Version](/business/nouns/version): every [Startup](/business/nouns/startup) in a Cohort runs the same [Version](/business/nouns/version) of a shared definition; a control Cohort keeps the prior one. `pinnedTo`, inverse [`pinnedCohorts`](/business/nouns/version#rel-pinned-cohorts). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Cohort.create](/business/nouns/cohort/create) | Creates a Cohort. Inherited from [Noun](/business/nouns/noun). | None. | `Cohort.created` | Two-way: `try`, `send`, `do` | | [Cohort.get](/business/nouns/cohort/get) | Returns one Cohort by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Cohort.list](/business/nouns/cohort/list) | Returns Cohorts, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Cohort.update](/business/nouns/cohort/update) | Changes the given properties of a Cohort. Inherited from [Noun](/business/nouns/noun). | None. | `Cohort.updated` | Two-way: `try`, `send`, `do` | | [Cohort.delete](/business/nouns/cohort/delete) | Deletes a Cohort; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Cohort.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Cohort.create` | Yes | Yes | Yes | No | | `Cohort.get` | Yes | Yes | Yes | Yes | | `Cohort.list` | Yes | Yes | Yes | Yes | | `Cohort.update` | Yes | Yes | Yes | No | | `Cohort.delete` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Add a cohort to ShiftNote. ``` **API** ```bash curl -X POST https://api.sb/shiftnote.app/cohorts \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"query":{}}' ``` ```json { "api": "https://api.sb/shiftnote.app", "cohort": { "$id": "https://api.sb/shiftnote.app/cohorts/cohort_1", "$type": "Cohort", "query": {} }, "action": { "$id": "https://api.sb/shiftnote.app/actions/action_1", "operation": "Cohort.create", "status": "done" }, "links": { "self": "https://api.sb/shiftnote.app/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const cohort = await $.Cohort.create({ query: {} }) ``` **CLI** ```bash npx startup-builder do Cohort.create --json '{"query":{}}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Cohort.create({ query: {} })" } } ``` ## Example A [Studio](/business/nouns/studio) rolls Keyless signup out to a first Cohort: 1% of its Startups with a priced API. A control Cohort of the same size stays on the prior Version. # export URL: /business/nouns/collection/export · Id: `verb:Collection.export` · Call: `await $.Collection.export({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Export writes a Collection’s records to a file or the Startup’s warehouse, once or on a schedule. Export writes a [Collection](/business/nouns/collection)’s records to a file or the [Startup](/business/nouns/startup)’s warehouse, once or on a schedule. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `collection` | [Collection](/business/nouns/collection) | Yes | The Collection to export. | | `to` | `string` | Yes | A file format, or the warehouse Integration that receives it. | | `cadence` | `string` | No | How often it repeats; omitted, it runs once. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `file` | [File](/business/nouns/file) | No | The exported File, for a one-time export. | | `collection` | [Collection](/business/nouns/collection) | Yes | The Collection exported. | ## Effects - Emits [`Collection.exported`](/business/events/Collection.exported). - Performed by the [Data Engineer](/agents/engineering/data-engineer). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Masks fields the caller’s Permissions hide. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Collection.export](/business/nouns/collection/export) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Export the latest collection. ``` **API** ```bash curl -X POST https://api.sb/tutorloop.com/collections/collection_1/export \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"to":"Example to"}' ``` ```json { "api": "https://api.sb/tutorloop.com", "file": { "$id": "https://api.sb/tutorloop.com/files/file_1", "$type": "File", "contentType": "Example content type", "size": 1 }, "collection": { "$id": "https://api.sb/tutorloop.com/collections/collection_1", "$type": "Collection", "id": "Example id", "type": [ "noun_1" ] }, "action": { "$id": "https://api.sb/tutorloop.com/actions/action_1", "operation": "Collection.export", "status": "done" }, "links": { "self": "https://api.sb/tutorloop.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { file, collection } = await $.Collection.export({ collection: 'collection_1', to: 'Example to' }) ``` **CLI** ```bash npx startup-builder do Collection.export --json '{"collection":"collection_1","to":"Example to"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Collection.export({ collection: 'collection_1', to: 'Example to' })" } } ``` Guides that call it: [Export my customers to CSV](/systems/data-and-insights/export-my-data). # Collection URL: /business/nouns/collection · Id: `noun:collection` > A Collection is a Thing with members, either listed one by one or defined by a saved query. A Collection is a [Thing](/business/nouns/thing) with members, either listed one by one or defined by a saved query. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `query` | `json` | No | The saved query that defines a dynamic Collection. |
Inherited from [Thing](/business/nouns/thing): 4 properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `id` | `string` | Yes | The stable identifier, which never changes. | | `type` | list of [Noun](/business/nouns/noun) | Yes | The Nouns this Thing is an instance of. | | `state` | `string` | No | The current state in its lifecycle. | | `outside` | `json` | No | The ids this Thing has in outside tools, one per Integration, so a re-run matches instead of duplicating. |
## Object ```json { "$id": "https://api.sb/kilnbakery.com/collections/collection_1", "$type": "Collection", "id": "Example id", "type": [ "noun_1" ], "state": "Example state", "outside": {}, "query": {} } ``` ## Relationships - A Collection **contains** many [Things](/business/nouns/thing): Members are listed one by one or matched by the Collection’s saved query; a [Thing](/business/nouns/thing) can belong to many Collections. `contains`, inverse [`memberOf`](/business/nouns/thing#rel-member-of). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Collection.export](/business/nouns/collection/export) | Export writes a Collection’s records to a file or the Startup’s warehouse, once or on a schedule. | [Data Engineer](/agents/engineering/data-engineer) | [`Collection.exported`](/business/events/Collection.exported) | Two-way: `try`, `send`, `do` | | [Collection.query](/business/nouns/collection/query) | Query reads any Nouns the caller’s Permissions allow, by SQL or a Relationship path, across every System in one call. | [Analyst](/agents/marketing/analyst) | [`Collection.queried`](/business/events/Collection.queried) | Two-way: `try`, `send`, `do` | | [Collection.create](/business/nouns/collection/create) | Creates a Collection. Inherited from [Noun](/business/nouns/noun). | None. | `Collection.created` | Two-way: `try`, `send`, `do` | | [Collection.get](/business/nouns/collection/get) | Returns one Collection by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Collection.list](/business/nouns/collection/list) | Returns Collections, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Collection.update](/business/nouns/collection/update) | Changes the given properties of a Collection. Inherited from [Noun](/business/nouns/noun). | None. | `Collection.updated` | Two-way: `try`, `send`, `do` | | [Collection.delete](/business/nouns/collection/delete) | Deletes a Collection; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Collection.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Collection.create` | Yes | Yes | Yes | No | | `Collection.get` | Yes | Yes | Yes | Yes | | `Collection.list` | Yes | Yes | Yes | Yes | | `Collection.update` | Yes | Yes | Yes | No | | `Collection.delete` | Yes | Yes | Yes | No | | `Collection.export` | Yes | Yes | Yes | No | | `Collection.query` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Query the latest collection. ``` **API** ```bash curl -X POST https://api.sb/tutorloop.com/collections/query \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"query":"Example query"}' ``` ```json { "api": "https://api.sb/tutorloop.com", "rows": {}, "collection": { "$id": "https://api.sb/tutorloop.com/collections/collection_1", "$type": "Collection", "id": "Example id", "type": [ "noun_1" ] }, "action": { "$id": "https://api.sb/tutorloop.com/actions/action_1", "operation": "Collection.query", "status": "done" }, "links": { "self": "https://api.sb/tutorloop.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { rows, collection } = await $.Collection.query({ query: 'Example query' }) ``` **CLI** ```bash npx startup-builder do Collection.query --json '{"query":"Example query"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Collection.query({ query: 'Example query' })" } } ``` ## Example The Collection "enterprise [Customers](/business/nouns/customer)" is a saved query for Customers with more than 50 seats. A new Customer at 51 seats joins it at once. # query URL: /business/nouns/collection/query · Id: `verb:Collection.query` · Call: `await $.Collection.query({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Query reads any Nouns the caller’s Permissions allow, by SQL or a Relationship path, across every System in one call. Query reads any [Nouns](/business/nouns/noun) the caller’s [Permissions](/business/nouns/permission) allow, by SQL or a [Relationship](/business/nouns/relationship) path, across every [System](/business/nouns/system) in one call. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `query` | `text` | Yes | SQL, or a Relationship path such as `customer.subscriptions.invoices`. | | `save` | `boolean` | No | True saves it as a Collection defined by the query. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `rows` | `json` | Yes | The matching records. | | `collection` | [Collection](/business/nouns/collection) | Yes | The Collection the query read. | ## Effects - Emits [`Collection.queried`](/business/events/Collection.queried). - Performed by the [Analyst](/agents/marketing/analyst). - Two-way: it runs at once, in the `try`, `send` and `do` modes. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Collection.query](/business/nouns/collection/query) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Query the latest collection. ``` **API** ```bash curl -X POST https://api.sb/tutorloop.com/collections/query \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"query":"Example query"}' ``` ```json { "api": "https://api.sb/tutorloop.com", "rows": {}, "collection": { "$id": "https://api.sb/tutorloop.com/collections/collection_1", "$type": "Collection", "id": "Example id", "type": [ "noun_1" ] }, "action": { "$id": "https://api.sb/tutorloop.com/actions/action_1", "operation": "Collection.query", "status": "done" }, "links": { "self": "https://api.sb/tutorloop.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { rows, collection } = await $.Collection.query({ query: 'Example query' }) ``` **CLI** ```bash npx startup-builder do Collection.query --json '{"query":"Example query"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Collection.query({ query: 'Example query' })" } } ``` Guides that call it: [Which integrations do people want](/start/guides/which-integrations-do-people-want). # Comment URL: /business/nouns/comment · Id: `noun:comment` > A Comment is an internal note by a Worker about a Thing, never sent to a Contact. A Comment is an internal note by a [Worker](/business/nouns/worker) about a [Thing](/business/nouns/thing), never sent to a [Contact](/business/nouns/contact). ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `body` | `text` | Yes | What it says. | ## Object ```json { "$id": "https://api.sb/shiftnote.app/comments/comment_1", "$type": "Comment", "body": "Example body" } ``` ## Relationships - A Comment **annotates** one [Thing](/business/nouns/thing): a Comment is an internal note on one [Thing](/business/nouns/thing), never sent to a [Contact](/business/nouns/contact). `annotates`, inverse [`comments`](/business/nouns/thing#rel-comments). - A Comment’s **author** is one [Worker](/business/nouns/worker): every Comment names the [Worker](/business/nouns/worker), human or agent, who wrote it. `author`, inverse [`writes`](/business/nouns/worker#rel-writes). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Comment.create](/business/nouns/comment/create) | Creates a Comment. Inherited from [Noun](/business/nouns/noun). | None. | `Comment.created` | Two-way: `try`, `send`, `do` | | [Comment.get](/business/nouns/comment/get) | Returns one Comment by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Comment.list](/business/nouns/comment/list) | Returns Comments, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Comment.update](/business/nouns/comment/update) | Changes the given properties of a Comment. Inherited from [Noun](/business/nouns/noun). | None. | `Comment.updated` | Two-way: `try`, `send`, `do` | | [Comment.delete](/business/nouns/comment/delete) | Deletes a Comment; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Comment.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Comment.create` | Yes | Yes | Yes | No | | `Comment.get` | Yes | Yes | Yes | Yes | | `Comment.list` | Yes | Yes | Yes | Yes | | `Comment.update` | Yes | Yes | Yes | No | | `Comment.delete` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Add a comment to RouteWise. ``` **API** ```bash curl -X POST https://api.sb/routewise.dev/comments \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"body":"Example body"}' ``` ```json { "api": "https://api.sb/routewise.dev", "comment": { "$id": "https://api.sb/routewise.dev/comments/comment_1", "$type": "Comment", "body": "Example body" }, "action": { "$id": "https://api.sb/routewise.dev/actions/action_1", "operation": "Comment.create", "status": "done" }, "links": { "self": "https://api.sb/routewise.dev/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const comment = await $.Comment.create({ body: 'Example body' }) ``` **CLI** ```bash npx startup-builder do Comment.create --json '{"body":"Example body"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Comment.create({ body: 'Example body' })" } } ``` ## Example A support [Agent](/business/nouns/agent) leaves a Comment on a [Conversation](/business/nouns/conversation): `refund approved, send confirmation`. The [Contact](/business/nouns/contact) never sees it. # Commission URL: /business/nouns/commission · Id: `noun:commission` > A Commission is what a Partner earns on the collected revenue its Referral brings, at a rate over a term, paid after a clawback window. A Commission is what a [Partner](/business/nouns/partner) earns on the collected revenue its [Referral](/business/nouns/referral) brings, at a rate over a term, paid after a clawback window. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `rate` | `number` | Yes | The share of collected revenue earned, as a percent, such as 20. Never randomized. | | `term` | `integer` | Yes | Months after the first payment over which revenue earns the rate, such as 12. Never randomized. | | `clawbackDays` | `integer` | Yes | Days a payment waits before it earns, so a refund inside the window earns nothing. | | `earned` | `money` | No | Collected revenue net of refunds, times the rate, for payments past the clawback window. | | `paid` | `money` | No | What has reached the Partner so far. | ## Object ```json { "$id": "https://api.sb/patentpad.com/commissions/commission_1", "$type": "Commission", "rate": 1, "term": 1, "clawbackDays": 1, "earned": { "amount": 499, "currency": "USD" }, "paid": { "amount": 499, "currency": "USD" } } ``` ## Relationships - A Commission **has** one [Referral](/business/nouns/referral): the Commission a [Partner](/business/nouns/partner)’s [Referral](/business/nouns/referral) earns on the revenue it brings, self-serve or through a [Deal](/business/nouns/deal). `referral`, inverse [`earns`](/business/nouns/referral#rel-earns). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Commission.pay](/business/nouns/commission/pay) | Pay transfers a Commission’s earned, unpaid amount to the Partner’s connected account through Stripe. | [Billing Specialist](/agents/finance/billing-specialist) | [`Commission.paid`](/business/events/Commission.paid) | One-way (money): `send`, `do` | | [Commission.create](/business/nouns/commission/create) | Creates a Commission. Inherited from [Noun](/business/nouns/noun). | None. | `Commission.created` | Two-way: `try`, `send`, `do` | | [Commission.get](/business/nouns/commission/get) | Returns one Commission by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Commission.list](/business/nouns/commission/list) | Returns Commissions, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Commission.update](/business/nouns/commission/update) | Changes the given properties of a Commission. Inherited from [Noun](/business/nouns/noun). | None. | `Commission.updated` | Two-way: `try`, `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Commission.create` | Yes | Yes | Yes | No | | `Commission.get` | Yes | Yes | Yes | Yes | | `Commission.list` | Yes | Yes | Yes | Yes | | `Commission.update` | Yes | Yes | Yes | No | | `Commission.pay` | Yes | No | No | No | ## Call it **Ask** ```text Pay the latest commission. ``` **API** ```bash curl -X POST https://api.sb/routewise.dev/commissions/commission_1/pay \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/routewise.dev", "commission": { "$id": "https://api.sb/routewise.dev/commissions/commission_1", "$type": "Commission", "rate": 1, "term": 1, "clawbackDays": 1 }, "transaction": { "$id": "https://api.sb/routewise.dev/transactions/transaction_1", "$type": "Transaction", "kind": "charge", "amount": { "amount": 25, "currency": "USD" } }, "action": { "$id": "https://api.sb/routewise.dev/actions/action_1", "operation": "Commission.pay", "status": "done" }, "links": { "self": "https://api.sb/routewise.dev/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { commission, transaction } = await $.Commission.pay({ commission: 'commission_1' }) ``` **CLI** ```bash npx startup-builder do Commission.pay --json '{"commission":"commission_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Commission.pay({ commission: 'commission_1' })" } } ``` ## Example An accounting firm refers a client to a payroll app on a Commission of 20% for 12 months with a 30-day clawback. The client pays $300 a month, so the firm earns $60 a month once each payment clears the window. # pay URL: /business/nouns/commission/pay · Id: `verb:Commission.pay` · Call: `await $.Commission.pay({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Pay transfers a Commission’s earned, unpaid amount to the Partner’s connected account through Stripe. Pay transfers a [Commission](/business/nouns/commission)’s earned, unpaid amount to the [Partner](/business/nouns/partner)’s connected account through Stripe. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `commission` | [Commission](/business/nouns/commission) | Yes | The Commission with an amount past its clawback window. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `commission` | [Commission](/business/nouns/commission) | Yes | The Commission, its `paid` raised by the transfer. | | `transaction` | [Transaction](/business/nouns/transaction) | Yes | The transfer as the rail reports it. | ## Effects - Emits [`Commission.paid`](/business/events/Commission.paid). - Performed by the [Billing Specialist](/agents/finance/billing-specialist). - One-way (money): it waits out its delay window, and runs in the `send` and `do` modes. - Pays only revenue past the clawback window; a later refund nets against the next payment. - Checks the payout Limit; above it, opens an Approval and the Action waits. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Commission.pay](/business/nouns/commission/pay) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Medium: one-way, bounded (money) | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | 1 business hour, in which a watcher can pause, redirect or cancel it; then it runs. | | Limit | The spend [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) or [Mandate](/business/nouns/mandate) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Pay the latest commission. ``` **API** ```bash curl -X POST https://api.sb/routewise.dev/commissions/commission_1/pay \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/routewise.dev", "commission": { "$id": "https://api.sb/routewise.dev/commissions/commission_1", "$type": "Commission", "rate": 1, "term": 1, "clawbackDays": 1 }, "transaction": { "$id": "https://api.sb/routewise.dev/transactions/transaction_1", "$type": "Transaction", "kind": "charge", "amount": { "amount": 25, "currency": "USD" } }, "action": { "$id": "https://api.sb/routewise.dev/actions/action_1", "operation": "Commission.pay", "status": "done" }, "links": { "self": "https://api.sb/routewise.dev/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { commission, transaction } = await $.Commission.pay({ commission: 'commission_1' }) ``` **CLI** ```bash npx startup-builder do Commission.pay --json '{"commission":"commission_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Commission.pay({ commission: 'commission_1' })" } } ``` # dissolve URL: /business/nouns/company/dissolve · Id: `verb:Company.dissolve` · Call: `await $.Company.dissolve({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Dissolve winds up a Company that holds no business: it files final returns and the certificate, and keeps every record. Dissolve winds up a [Company](/business/nouns/company) that holds no business: it files final returns and the certificate, and keeps every record. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `company` | [Company](/business/nouns/company) | Yes | The Company to wind up. | | `reason` | `text` | Yes | Why it ends, recorded as a Decision. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `company` | [Company](/business/nouns/company) | Yes | The dissolved Company, kept forever. | ## Effects - Emits [`Company.dissolved`](/business/events/Company.dissolved). - Performed by the [Legal Lead](/agents/legal/legal-lead). - One-way (money, customer): it waits out its delay window, and runs in the `send` and `do` modes. - Runs through [Company dissolution](/systems/legal-and-corporate/entity-dissolution). - Waits for the Founder, as an officer, to sign the certificate of dissolution: the legal floor. - Ends the registered agent and every recurring filing. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Company.dissolve](/business/nouns/company/dissolve) | | The record is not in a state that allows this Verb, so the call is refused. | [`refused`](/code/api/errors/refused) | Read the record, run the Verb that moves it to an allowed state, then retry. | [Company.dissolve](/business/nouns/company/dissolve) | ## When it waits | Gate | Default | | --- | --- | | Decision class | High: one-way, broad (money, customer) | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | 1 business day, in which a watcher can pause, redirect or cancel it; then it runs. | | Limit | The spend [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) or [Mandate](/business/nouns/mandate) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Dissolve my company. ``` **API** ```bash curl -X POST https://api.sb/petpantry.shop/companies/company_1/dissolve \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"reason":"Example reason"}' ``` ```json { "api": "https://api.sb/petpantry.shop", "company": { "$id": "https://api.sb/petpantry.shop/companies/company_1", "$type": "Company", "name": "PetPantry", "legalName": "PetPantry Inc.", "jurisdiction": "US-DE", "status": "dissolved" }, "action": { "$id": "https://api.sb/petpantry.shop/actions/action_1", "operation": "Company.dissolve", "status": "done" }, "links": { "self": "https://api.sb/petpantry.shop/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const company = await $.Company.dissolve({ company: 'company_1', reason: 'Example reason' }) ``` **CLI** ```bash npx startup-builder do Company.dissolve --json '{"company":"company_1","reason":"Example reason"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Company.dissolve({ company: 'company_1', reason: 'Example reason' })" } } ``` Guides that call it: [Wind down my startup](/business/wind-down-my-startup). # incorporate URL: /business/nouns/company/incorporate · Id: `verb:Company.incorporate` · Call: `await $.Company.incorporate({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Incorporate forms a Company in a chosen jurisdiction, with its founders, shares and registered agent on record. Incorporate forms a [Company](/business/nouns/company) in a chosen jurisdiction, with its founders, shares and registered agent on record. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `legalName` | `string` | Yes | The registered name. | | `jurisdiction` | `string` | Yes | Where the Company forms. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `company` | [Company](/business/nouns/company) | Yes | The new Company. | ## Effects - Emits [`Company.incorporated`](/business/events/Company.incorporated). - Performed by the [Founder](/agents/founding/founder). - One-way (money): it waits out its delay window, and runs in the `send` and `do` modes. - Runs through [Company formation](/systems/legal-and-corporate/entity-formation), which files the certificate and appoints the first directors. - Waits for the Founder, as an officer, to sign the formation documents: the legal floor. - Opens the Company’s cap table. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The input does not match the schema of the operation. | [`invalid-input`](/code/api/errors/invalid-input) | Read the schema of the operation, then send every required field with the right type. | [Company.incorporate](/business/nouns/company/incorporate) | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Company.incorporate](/business/nouns/company/incorporate) | | The record is not in a state that allows this Verb, so the call is refused. | [`refused`](/code/api/errors/refused) | Read the record, run the Verb that moves it to an allowed state, then retry. | [Company.incorporate](/business/nouns/company/incorporate) | ## When it waits | Gate | Default | | --- | --- | | Decision class | High: one-way, broad (money) | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | 1 business day, in which a watcher can pause, redirect or cancel it; then it runs. | | Limit | The spend [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) or [Mandate](/business/nouns/mandate) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Incorporate the company “PatentPad Inc.” ``` **API** ```bash curl -X POST https://api.sb/patentpad.com/companies/incorporate \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"legalName":"PatentPad Inc.","jurisdiction":"US-DE"}' ``` ```json { "api": "https://api.sb/patentpad.com", "company": { "$id": "https://api.sb/patentpad.com/companies/company_1", "$type": "Company", "name": "PatentPad", "legalName": "PatentPad Inc.", "jurisdiction": "US-DE", "status": "incorporated" }, "action": { "$id": "https://api.sb/patentpad.com/actions/action_1", "operation": "Company.incorporate", "status": "done" }, "links": { "self": "https://api.sb/patentpad.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const company = await $.Company.incorporate({ legalName: 'PatentPad Inc.', jurisdiction: 'US-DE' }) ``` **CLI** ```bash npx startup-builder do Company.incorporate --json '{"legalName":"PatentPad Inc.","jurisdiction":"US-DE"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Company.incorporate({ legalName: 'PatentPad Inc.', jurisdiction: 'US-DE' })" } } ``` Guides that call it: [Form my company](/systems/legal-and-corporate/form-my-company). # Company URL: /business/nouns/company · Id: `noun:company` > A Company is a legal entity that holds Startups, signs Agreements, and owns equity, authority, and profit rights. A Company is a legal entity that holds [Startups](/business/nouns/startup), signs [Agreements](/business/nouns/agreement), and owns equity, authority, and profit rights. A Startup that [graduates](/business/nouns/startup/graduate) moves to a Company of its own. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `legalName` | `string` | Yes | The registered name. | | `jurisdiction` | `string` | Yes | Where it is incorporated. | | `status` | `string` | Yes | One of `forming`, `incorporated` or `dissolved`. |
Inherited from [Party](/business/nouns/party): 1 property | Property | Type | Required | Description | | --- | --- | --- | --- | | `name` | `string` | Yes | The legal or personal name. |
## Object ```json { "$id": "https://api.sb/routewise.dev/companies/company_1", "$type": "Company", "name": "RouteWise", "legalName": "RouteWise Inc.", "jurisdiction": "US-DE", "status": "forming" } ``` ## Relationships - A Company **is controlled by** one [Studio](/business/nouns/studio): a [Studio](/business/nouns/studio) controls the holding Companies that are owner of record for its [Startups](/business/nouns/startup). `controlledBy`, inverse [`controls`](/business/nouns/studio#rel-controls). - A Company **holds** many [Startups](/business/nouns/startup): the holding Company is the [Startup](/business/nouns/startup)’s owner of record: it signs its [Agreements](/business/nouns/agreement) and owns its profit rights. `holds`, inverse [`heldBy`](/business/nouns/startup#rel-held-by). - A Company **has** many [Instruments](/business/nouns/instrument): an [Instrument](/business/nouns/instrument) is a right in one Company and counts in its fully diluted cap table. `instruments`, inverse [`issuedBy`](/business/nouns/instrument#rel-issued-by). - A Company **keeps** many [Suppressions](/business/nouns/suppression): a Company’s [Suppressions](/business/nouns/suppression) bind every [Startup](/business/nouns/startup) it holds: no commercial [Message](/business/nouns/message) goes to a suppressed address. `keeps`, inverse [`keptBy`](/business/nouns/suppression#rel-kept-by). - A Company **is known as** many [Organizations](/business/nouns/organization): each [Startup](/business/nouns/startup)’s own view of an outside party resolves to the one legal entity behind it. `knownAs`, inverse [`resolvesTo`](/business/nouns/organization#rel-resolves-to). - A Company **has** many [Pay Runs](/business/nouns/pay-run): a [Pay Run](/business/nouns/pay-run) is paid by one Company, the employer of record for everyone in it. `payRuns`, inverse [`paidBy`](/business/nouns/pay-run#rel-paid-by). - A Company **has** many [Shares](/business/nouns/share): a [Share](/business/nouns/share) is issued by one Company and sits on that Company’s cap table. `shares`, inverse [`issuedBy`](/business/nouns/share#rel-issued-by). ## Lifecycle | State | Meaning | Moves to | | --- | --- | --- | | `forming` (first) | Its founders, jurisdiction and shares are chosen, and no formation filing is accepted yet. | `incorporated` by [Company.incorporate](/business/nouns/company/incorporate) | | `incorporated` | A registered legal entity that signs Agreements, holds accounts and owns equity. | `dissolved` by [Company.dissolve](/business/nouns/company/dissolve) | | `dissolved` | Wound up, with its final returns filed and every record kept. | None: it ends here. | ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Company.dissolve](/business/nouns/company/dissolve) | Dissolve winds up a Company that holds no business: it files final returns and the certificate, and keeps every record. | [Legal Lead](/agents/legal/legal-lead) | [`Company.dissolved`](/business/events/Company.dissolved) | One-way (money, customer): `send`, `do` | | [Company.incorporate](/business/nouns/company/incorporate) | Incorporate forms a Company in a chosen jurisdiction, with its founders, shares and registered agent on record. | [Founder](/agents/founding/founder) | [`Company.incorporated`](/business/events/Company.incorporated) | One-way (money): `send`, `do` | | [Company.register](/business/nouns/company/register) | Register applies for a sales tax, VAT or GST registration in one jurisdiction and records the grant as a Credential. | [Finance Lead](/agents/finance/finance-lead) | [`Company.registered`](/business/events/Company.registered) | One-way: `send`, `do` | | [Company.submit](/business/nouns/company/submit) | Submit files one tax return for a jurisdiction and its Periods, pays the tax due, and keeps the return as a Document. | [Finance Lead](/agents/finance/finance-lead) | [`Company.submitted`](/business/events/Company.submitted) | One-way (money): `send`, `do` | | [Company.create](/business/nouns/company/create) | Creates a Company. Inherited from [Noun](/business/nouns/noun). | None. | `Company.created` | Two-way: `try`, `send`, `do` | | [Company.get](/business/nouns/company/get) | Returns one Company by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Company.list](/business/nouns/company/list) | Returns Companies, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Company.update](/business/nouns/company/update) | Changes the given properties of a Company. Inherited from [Noun](/business/nouns/noun). | None. | `Company.updated` | Two-way: `try`, `send`, `do` | A Company is never deleted: it ends by [Company.dissolve](/business/nouns/company/dissolve), and its records stay. ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Company.create` | Yes | Yes | Yes | No | | `Company.get` | Yes | Yes | Yes | Yes | | `Company.list` | Yes | Yes | Yes | Yes | | `Company.update` | Yes | Yes | Yes | No | | `Company.dissolve` | Yes | No | No | No | | `Company.incorporate` | Yes | No | No | No | | `Company.register` | Yes | No | No | No | | `Company.submit` | Yes | No | No | No | ## Call it **Ask** ```text Incorporate the company “PatentPad Inc.” ``` **API** ```bash curl -X POST https://api.sb/patentpad.com/companies/incorporate \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"legalName":"PatentPad Inc.","jurisdiction":"US-DE"}' ``` ```json { "api": "https://api.sb/patentpad.com", "company": { "$id": "https://api.sb/patentpad.com/companies/company_1", "$type": "Company", "name": "PatentPad", "legalName": "PatentPad Inc.", "jurisdiction": "US-DE", "status": "incorporated" }, "action": { "$id": "https://api.sb/patentpad.com/actions/action_1", "operation": "Company.incorporate", "status": "done" }, "links": { "self": "https://api.sb/patentpad.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const company = await $.Company.incorporate({ legalName: 'PatentPad Inc.', jurisdiction: 'US-DE' }) ``` **CLI** ```bash npx startup-builder do Company.incorporate --json '{"legalName":"PatentPad Inc.","jurisdiction":"US-DE"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Company.incorporate({ legalName: 'PatentPad Inc.', jurisdiction: 'US-DE' })" } } ``` ## Example One Company holds a résumé-review shop, a cover-letter [Agent](/business/nouns/agent) and a job-board directory. It signs their Agreements, keeps one [Suppression](/business/nouns/suppression) list for all three, and receives their profit. # register URL: /business/nouns/company/register · Id: `verb:Company.register` · Call: `await $.Company.register({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Register applies for a sales tax, VAT or GST registration in one jurisdiction and records the grant as a Credential. Register applies for a sales tax, VAT or GST registration in one jurisdiction and records the grant as a [Credential](/business/nouns/credential). ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `jurisdiction` | `string` | Yes | Where to register, such as `US-TX` or `EU-DE`. | | `kind` | `string` | Yes | Which tax the registration collects. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `credential` | [Credential](/business/nouns/credential) | Yes | The registration, with its number and filing frequency once granted. | | `company` | [Company](/business/nouns/company) | Yes | The Company now registered in the jurisdiction. | ## Effects - Emits [`Company.registered`](/business/events/Company.registered). - Performed by the [Finance Lead](/agents/finance/finance-lead). - One-way: it waits out its delay window, and runs in the `send` and `do` modes. - The tax-filing Workflow calls it when sales cross a threshold, totaled across every Startup the Company holds. - Collection starts on the first Order placed after the authority grants the Credential. - Creates the recurring return Task at the frequency the authority assigns. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Company.register](/business/nouns/company/register) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Medium: one-way, bounded | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | 1 business hour, in which a watcher can pause, redirect or cancel it; then it runs. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Register my company. ``` **API** ```bash curl -X POST https://api.sb/quietcopy.com/companies/register \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"jurisdiction":"US-TX","kind":"salesTax"}' ``` ```json { "api": "https://api.sb/quietcopy.com", "credential": { "$id": "https://api.sb/quietcopy.com/credentials/credential_1", "$type": "Credential", "issuer": "Example issuer", "jurisdiction": "US-DE" }, "company": { "$id": "https://api.sb/quietcopy.com/companies/company_1", "$type": "Company", "name": "QuietCopy", "legalName": "QuietCopy Inc.", "jurisdiction": "US-DE", "status": "forming" }, "action": { "$id": "https://api.sb/quietcopy.com/actions/action_1", "operation": "Company.register", "status": "done" }, "links": { "self": "https://api.sb/quietcopy.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { credential, company } = await $.Company.register({ jurisdiction: 'US-TX', kind: 'salesTax' }) ``` **CLI** ```bash npx startup-builder do Company.register --json '{"jurisdiction":"US-TX","kind":"salesTax"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Company.register({ jurisdiction: 'US-TX', kind: 'salesTax' })" } } ``` Next: [`Company.submit`](/business/nouns/company/submit) (in `guide:handle-sales-tax`). Guides that call it: [Handle sales tax](/systems/finance/handle-sales-tax). # submit URL: /business/nouns/company/submit · Id: `verb:Company.submit` · Call: `await $.Company.submit({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Submit files one tax return for a jurisdiction and its Periods, pays the tax due, and keeps the return as a Document. Submit files one tax return for a jurisdiction and its [Periods](/business/nouns/period), pays the tax due, and keeps the return as a [Document](/business/nouns/document). ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `jurisdiction` | `string` | Yes | Where the return is filed, such as `US-TX`. | | `kind` | `string` | Yes | What the return reports: sales tax, VAT, GST, income, franchise tax, or an information return. | | `periods` | list of [Period](/business/nouns/period) | Yes | The locked Periods the return covers: one month, a quarter or a year. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `taxReturn` | [Document](/business/nouns/document) | Yes | The return as submitted, with the authority’s confirmation. | | `payment` | [Transaction](/business/nouns/transaction) | No | The payment of the tax due; none for an information return. | | `company` | [Company](/business/nouns/company) | Yes | The Company that filed the return. | ## Effects - Emits [`Company.submitted`](/business/events/Company.submitted). - Performed by the [Finance Lead](/agents/finance/finance-lead). - One-way (money): it waits out its delay window, and runs in the `send` and `do` modes. - Computes the return from the Orders, Entries and payouts of its Periods. - A return with a sworn declaration waits for the signature of the Human the legal floor names. - Completes the return Task the registration created for the same jurisdiction and Periods. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Company.submit](/business/nouns/company/submit) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Medium: one-way, bounded (money) | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | 1 business hour, in which a watcher can pause, redirect or cancel it; then it runs. | | Limit | The spend [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) or [Mandate](/business/nouns/mandate) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Submit my company with a period. ``` **API** ```bash curl -X POST https://api.sb/shiftnote.app/companies/submit \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"jurisdiction":"US-TX","kind":"salesTax","periods":["period_1"]}' ``` ```json { "api": "https://api.sb/shiftnote.app", "taxReturn": { "$id": "https://api.sb/shiftnote.app/documents/document_1", "$type": "Document", "form": "document" }, "payment": { "$id": "https://api.sb/shiftnote.app/transactions/transaction_1", "$type": "Transaction", "kind": "charge", "amount": { "amount": 79, "currency": "USD" } }, "company": { "$id": "https://api.sb/shiftnote.app/companies/company_1", "$type": "Company", "name": "ShiftNote", "legalName": "ShiftNote Inc.", "jurisdiction": "US-DE", "status": "forming" }, "action": { "$id": "https://api.sb/shiftnote.app/actions/action_1", "operation": "Company.submit", "status": "done" }, "links": { "self": "https://api.sb/shiftnote.app/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { taxReturn, payment, company } = await $.Company.submit({ jurisdiction: 'US-TX', kind: 'salesTax', periods: ['period_1'] }) ``` **CLI** ```bash npx startup-builder do Company.submit --json '{"jurisdiction":"US-TX","kind":"salesTax","periods":["period_1"]}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Company.submit({ jurisdiction: 'US-TX', kind: 'salesTax', periods: ['period_1'] })" } } ``` Guides that call it: [Handle sales tax](/systems/finance/handle-sales-tax). # Component URL: /business/nouns/component · Id: `noun:component` > A Component is a named block of a Page, such as a hero, a pricing table, or a form, filled from records through typed props. A Component is a named block of a [Page](/business/nouns/page), such as a hero, a pricing table, or a form, filled from records through typed props. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `name` | `string` | Yes | The name a Template places it by, such as `Pricing`. | | `props` | `json` | Yes | The schema of the props it accepts. | | `region` | `string` | No | Where it sits: `header`, `section`, `footer`, or `notice`. | | `interactive` | `boolean` | No | True when it runs code in the browser; it still renders a static still without it. | ## Object ```json { "$id": "https://api.sb/patentpad.com/components/component_1", "$type": "Component", "name": "PatentPad", "props": {}, "region": "header", "interactive": true } ``` ## Relationships - A Component **is placed by** many [Templates](/business/nouns/template): a [Template](/business/nouns/template) places named Components, such as `Pricing`, and fills their props from records. `placedBy`, inverse [`places`](/business/nouns/template#rel-places). - A Component **is used on** many [Pages](/business/nouns/page): a [Page](/business/nouns/page) is assembled from Components, each filled from records. `usedOn`, inverse [`uses`](/business/nouns/page#rel-uses). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Component.create](/business/nouns/component/create) | Creates a Component. Inherited from [Noun](/business/nouns/noun). | None. | `Component.created` | Two-way: `try`, `send`, `do` | | [Component.get](/business/nouns/component/get) | Returns one Component by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Component.list](/business/nouns/component/list) | Returns Components, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Component.update](/business/nouns/component/update) | Changes the given properties of a Component. Inherited from [Noun](/business/nouns/noun). | None. | `Component.updated` | Two-way: `try`, `send`, `do` | | [Component.delete](/business/nouns/component/delete) | Deletes a Component; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Component.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Component.create` | Yes | Yes | Yes | No | | `Component.get` | Yes | Yes | Yes | Yes | | `Component.list` | Yes | Yes | Yes | Yes | | `Component.update` | Yes | Yes | Yes | No | | `Component.delete` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Add a component to ShiftNote. ``` **API** ```bash curl -X POST https://api.sb/shiftnote.app/components \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"name":"ShiftNote","props":{}}' ``` ```json { "api": "https://api.sb/shiftnote.app", "component": { "$id": "https://api.sb/shiftnote.app/components/component_1", "$type": "Component", "name": "ShiftNote", "props": {} }, "action": { "$id": "https://api.sb/shiftnote.app/actions/action_1", "operation": "Component.create", "status": "done" }, "links": { "self": "https://api.sb/shiftnote.app/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const component = await $.Component.create({ name: 'ShiftNote', props: {} }) ``` **CLI** ```bash npx startup-builder do Component.create --json '{"name":"ShiftNote","props":{}}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Component.create({ name: 'ShiftNote', props: {} })" } } ``` ## Example The pricing [Page](/business/nouns/page) of a scheduling [SaaS](/products/templates/saas) places a `Pricing` Component in its main region, fed by the published [Offers](/business/nouns/offer). Publishing a $29 team Offer adds a column on every Page that uses the Component. # Consent URL: /business/nouns/consent · Id: `noun:consent` > A Consent is a person’s grant for one Purpose, with its basis, region, notice, evidence, and expiry. A Consent is a person’s grant for one [Purpose](/business/nouns/purpose), with its basis, region, notice, evidence, and expiry. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `basis` | `string` | Yes | The lawful basis, such as consent or contract. Never randomized. | | `region` | `string` | No | The jurisdiction whose rules apply. Never randomized. | | `withdrawnAt` | `datetime` | No | When the person withdrew it. Never randomized. | ## Object ```json { "$id": "https://api.sb/petpantry.shop/consents/consent_1", "$type": "Consent", "basis": "Example basis", "region": "Example region", "withdrawnAt": "2026-10-22T12:00:00Z" } ``` ## Relationships - A Consent **covers** one [Purpose](/business/nouns/purpose): the [Purpose](/business/nouns/purpose) the Consent permits processing for, and nothing beyond it. `covers`, inverse [`consents`](/business/nouns/purpose#rel-consents). - A Consent **is given by** one [Contact](/business/nouns/contact): a [Contact](/business/nouns/contact) grants Consents, each for one [Purpose](/business/nouns/purpose), with its basis and expiry. `givenBy`, inverse [`gives`](/business/nouns/contact#rel-gives). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Consent.withdraw](/business/nouns/consent/withdraw) | Withdraw ends a Consent at once: processing for its Purpose stops, and the record is kept. | [Privacy Officer](/agents/legal/privacy-officer) | [`Consent.withdrawn`](/business/events/Consent.withdrawn) | Two-way: `try`, `send`, `do` | | [Consent.create](/business/nouns/consent/create) | Creates a Consent. Inherited from [Noun](/business/nouns/noun). | None. | `Consent.created` | Two-way: `try`, `send`, `do` | | [Consent.get](/business/nouns/consent/get) | Returns one Consent by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Consent.list](/business/nouns/consent/list) | Returns Consents, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Consent.update](/business/nouns/consent/update) | Changes the given properties of a Consent. Inherited from [Noun](/business/nouns/noun). | None. | `Consent.updated` | Two-way: `try`, `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Consent.create` | Yes | Yes | Yes | No | | `Consent.get` | Yes | Yes | Yes | Yes | | `Consent.list` | Yes | Yes | Yes | Yes | | `Consent.update` | Yes | Yes | Yes | No | | `Consent.withdraw` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Withdraw the latest consent. ``` **API** ```bash curl -X POST https://api.sb/tutorloop.com/consents/consent_1/withdraw \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/tutorloop.com", "consent": { "$id": "https://api.sb/tutorloop.com/consents/consent_1", "$type": "Consent", "basis": "Example basis" }, "action": { "$id": "https://api.sb/tutorloop.com/actions/action_1", "operation": "Consent.withdraw", "status": "done" }, "links": { "self": "https://api.sb/tutorloop.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const consent = await $.Consent.withdraw({ consent: 'consent_1' }) ``` **CLI** ```bash npx startup-builder do Consent.withdraw --json '{"consent":"consent_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Consent.withdraw({ consent: 'consent_1' })" } } ``` ## Example A visitor ticks a box for product updates on a pricing [Page](/business/nouns/page). The Consent records the marketing [Purpose](/business/nouns/purpose), the notice shown, the time, and a two-year expiry. # withdraw URL: /business/nouns/consent/withdraw · Id: `verb:Consent.withdraw` · Call: `await $.Consent.withdraw({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Withdraw ends a Consent at once: processing for its Purpose stops, and the record is kept. Withdraw ends a [Consent](/business/nouns/consent) at once: processing for its [Purpose](/business/nouns/purpose) stops, and the record stays as proof. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `consent` | [Consent](/business/nouns/consent) | Yes | The Consent to end. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `consent` | [Consent](/business/nouns/consent) | Yes | The withdrawn Consent. | ## Effects - Emits [`Consent.withdrawn`](/business/events/Consent.withdrawn). - Performed by the [Privacy Officer](/agents/legal/privacy-officer). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Stops every queued Action that relies on the Consent. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Consent.withdraw](/business/nouns/consent/withdraw) | | The record is not in a state that allows this Verb, so the call is refused. | [`refused`](/code/api/errors/refused) | Read the record, run the Verb that moves it to an allowed state, then retry. | [Consent.withdraw](/business/nouns/consent/withdraw) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Medium: two-way, visible | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | 1 business hour, in which a watcher can pause, redirect or cancel it; then it runs. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Withdraw the latest consent. ``` **API** ```bash curl -X POST https://api.sb/tutorloop.com/consents/consent_1/withdraw \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/tutorloop.com", "consent": { "$id": "https://api.sb/tutorloop.com/consents/consent_1", "$type": "Consent", "basis": "Example basis" }, "action": { "$id": "https://api.sb/tutorloop.com/actions/action_1", "operation": "Consent.withdraw", "status": "done" }, "links": { "self": "https://api.sb/tutorloop.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const consent = await $.Consent.withdraw({ consent: 'consent_1' }) ``` **CLI** ```bash npx startup-builder do Consent.withdraw --json '{"consent":"consent_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Consent.withdraw({ consent: 'consent_1' })" } } ``` # enrich URL: /business/nouns/contact/enrich · Id: `verb:Contact.enrich` · Call: `await $.Contact.enrich({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Enrich fills a Contact’s missing fields from outside sources and marks each value with where it came from. Enrich fills a [Contact](/business/nouns/contact)’s missing fields from outside sources and marks each value with where it came from. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `contact` | [Contact](/business/nouns/contact) | Yes | The Contact to enrich. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `contact` | [Contact](/business/nouns/contact) | Yes | The enriched Contact. | ## Effects - Emits [`Contact.enriched`](/business/events/Contact.enriched). - Performed by the [Prospector](/agents/sales/prospector). - Meters each lookup against the Startup’s usage Limit. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Contact.enrich](/business/nouns/contact/enrich) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Enrich the contact Daniel Okafor. ``` **API** ```bash curl -X POST https://api.sb/shiftnote.app/contacts/contact_1/enrich \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/shiftnote.app", "contact": { "$id": "https://api.sb/shiftnote.app/contacts/contact_1", "$type": "Contact", "email": "daniel@shiftnote.app", "phone": "Example phone" }, "action": { "$id": "https://api.sb/shiftnote.app/actions/action_1", "operation": "Contact.enrich", "status": "done" }, "links": { "self": "https://api.sb/shiftnote.app/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const contact = await $.Contact.enrich({ contact: 'contact_1' }) ``` **CLI** ```bash npx startup-builder do Contact.enrich --json '{"contact":"contact_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Contact.enrich({ contact: 'contact_1' })" } } ``` # enroll URL: /business/nouns/contact/enroll · Id: `verb:Contact.enroll` · Call: `await $.Contact.enroll({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Enroll adds a Contact to a Sequence, which sends its steps until the Contact replies or exits. Enroll adds a [Contact](/business/nouns/contact) to a [Sequence](/business/nouns/sequence), which sends its steps until the Contact replies or exits. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `contact` | [Contact](/business/nouns/contact) | Yes | The Contact to enroll. | | `sequence` | [Sequence](/business/nouns/sequence) | Yes | The Sequence to run. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `contact` | [Contact](/business/nouns/contact) | Yes | The enrolled Contact. | | `enrollment` | [Enrollment](/business/nouns/enrollment) | Yes | The Enrollment that records this Contact’s run through the Sequence. | ## Effects - Emits [`Contact.enrolled`](/business/events/Contact.enrolled). - Performed by the [Prospector](/agents/sales/prospector). - Refuses a suppressed Contact or one with no consent for the Sequence’s purpose. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Contact.enroll](/business/nouns/contact/enroll) | | The record is not in a state that allows this Verb, so the call is refused. | [`refused`](/code/api/errors/refused) | Read the record, run the Verb that moves it to an allowed state, then retry. | [Contact.enroll](/business/nouns/contact/enroll) | | A suppressed Contact or one with no consent for the Sequence’s purpose | [`refused`](/code/api/errors/refused) | Clear what the check names, then call it again. | [Contact.enroll](/business/nouns/contact/enroll) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Enroll the contact Malik Owens with a sequence. ``` **API** ```bash curl -X POST https://api.sb/tutorloop.com/contacts/contact_1/enroll \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"sequence":"sequence_1"}' ``` ```json { "api": "https://api.sb/tutorloop.com", "contact": { "$id": "https://api.sb/tutorloop.com/contacts/contact_1", "$type": "Contact", "email": "malik@tutorloop.com", "phone": "Example phone" }, "enrollment": { "$id": "https://api.sb/tutorloop.com/enrollments/enrollment_1", "$type": "Enrollment", "status": "active", "step": "Example step" }, "action": { "$id": "https://api.sb/tutorloop.com/actions/action_1", "operation": "Contact.enroll", "status": "done" }, "links": { "self": "https://api.sb/tutorloop.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { contact, enrollment } = await $.Contact.enroll({ contact: 'contact_1', sequence: 'sequence_1' }) ``` **CLI** ```bash npx startup-builder do Contact.enroll --json '{"contact":"contact_1","sequence":"sequence_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Contact.enroll({ contact: 'contact_1', sequence: 'sequence_1' })" } } ``` # Contact URL: /business/nouns/contact · Id: `noun:contact` > A Contact is a person or Agent a Startup knows by at least one address, where Consent to message them is recorded. A Contact is a person or [Agent](/business/nouns/agent) a [Startup](/business/nouns/startup) knows by at least one address, where [Consent](/business/nouns/consent) to message them is recorded. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `email` | `email` | No | The primary email address. | | `phone` | `string` | No | The primary phone number. | | `name` | `string` | No | The name the Contact goes by. | Inherits from [Party](/business/nouns/party), which adds no properties of its own. ## Object ```json { "$id": "https://api.sb/tutorloop.com/contacts/contact_1", "$type": "Contact", "email": "malik@tutorloop.com", "phone": "Example phone", "name": "TutorLoop" } ``` ## Relationships - A Contact **becomes** one [Customer](/business/nouns/customer): a Contact becomes a [Customer](/business/nouns/customer) on accepting an [Offer](/business/nouns/offer). `becomes`, inverse [`contact`](/business/nouns/customer#rel-contact). - A Contact **is enrolled in** many [Sequences](/business/nouns/sequence): a [Sequence](/business/nouns/sequence) runs for an enrolled Contact until a reply, a purchase, or another exit [Event](/business/nouns/event) ends it. `enrolledIn`, inverse [`enrolls`](/business/nouns/sequence#rel-enrolls). - A Contact **has** many [Enrollments](/business/nouns/enrollment): the Contact this run belongs to; pausing one Contact’s nurture pauses this [Enrollment](/business/nouns/enrollment). `enrollments`, inverse [`runsFor`](/business/nouns/enrollment#rel-runs-for). - A Contact **gives** many [Consents](/business/nouns/consent): a Contact grants [Consents](/business/nouns/consent), each for one [Purpose](/business/nouns/purpose), with its basis and expiry. `gives`, inverse [`givenBy`](/business/nouns/consent#rel-given-by). - A Contact **has** many [Registrations](/business/nouns/registration): each [Registration](/business/nouns/registration) holds one Contact’s place; one Contact registers for many [Gatherings](/business/nouns/gathering). `registrations`, inverse [`names`](/business/nouns/registration#rel-names). - A Contact **resolves to** one [Person](/business/nouns/person): each Contact is one [Startup](/business/nouns/startup)’s view of a [Person](/business/nouns/person) shared across every Startup that knows them. `resolvesTo`, inverse [`contacts`](/business/nouns/person#rel-contacts). - A Contact **works at** one [Organization](/business/nouns/organization): a Contact works for one [Organization](/business/nouns/organization), as this [Startup](/business/nouns/startup) knows it. `worksAt`, inverse [`people`](/business/nouns/organization#rel-people). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Contact.enrich](/business/nouns/contact/enrich) | Enrich fills a Contact’s missing fields from outside sources and marks each value with where it came from. | [Prospector](/agents/sales/prospector) | [`Contact.enriched`](/business/events/Contact.enriched) | None. | | [Contact.enroll](/business/nouns/contact/enroll) | Enroll adds a Contact to a Sequence, which sends its steps until the Contact replies or exits. | [Prospector](/agents/sales/prospector) | [`Contact.enrolled`](/business/events/Contact.enrolled) | None. | | [Contact.merge](/business/nouns/contact/merge) | Merge joins a duplicate Contact into another, keeping every link, Message and Event on the one that remains. | [Sales Lead](/agents/sales/sales-lead) | [`Contact.merged`](/business/events/Contact.merged) | One-way: `send`, `do` | | [Gathering.register](/business/nouns/gathering/register) | Register gives a Contact a place at a Gathering, or a waitlist place when the Gathering is full. | [Marketing Lead](/agents/marketing/marketing-lead) | [`Gathering.registered`](/business/events/Gathering.registered) | Two-way: `try`, `send`, `do` | | [Quote.request](/business/nouns/quote/request) | Request asks a Startup for terms on one or more Offers, with the volume, term or scope wanted. | [Contact](/business/nouns/contact) | [`Quote.requested`](/business/events/Quote.requested) | None. | | [Contact.subscribe](/business/nouns/contact/subscribe) | Subscribe records a Contact’s chosen topics and frequency from the hosted preference page, with Consent for each topic. | [Marketing Lead](/agents/marketing/marketing-lead) | [`Contact.subscribed`](/business/events/Contact.subscribed) | Two-way: `try`, `send`, `do` | | [Contact.suppress](/business/nouns/contact/suppress) | Suppress records a Suppression for a Contact’s address, which every Startup honors forever. | [Prospector](/agents/sales/prospector) | [`Contact.suppressed`](/business/events/Contact.suppressed) | None. | | [Contact.unsubscribe](/business/nouns/contact/unsubscribe) | Unsubscribe stops commercial Messages to a Contact in one click, for one topic or all, honored at once. | [Marketing Lead](/agents/marketing/marketing-lead) | [`Contact.unsubscribed`](/business/events/Contact.unsubscribed) | Two-way: `try`, `send`, `do` | | [Consent.withdraw](/business/nouns/consent/withdraw) | Withdraw ends a Consent at once: processing for its Purpose stops, and the record is kept. | [Privacy Officer](/agents/legal/privacy-officer) | [`Consent.withdrawn`](/business/events/Consent.withdrawn) | Two-way: `try`, `send`, `do` | | [Contact.create](/business/nouns/contact/create) | Creates a Contact. Inherited from [Noun](/business/nouns/noun). | None. | `Contact.created` | Two-way: `try`, `send`, `do` | | [Contact.get](/business/nouns/contact/get) | Returns one Contact by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Contact.list](/business/nouns/contact/list) | Returns Contacts, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Contact.update](/business/nouns/contact/update) | Changes the given properties of a Contact. Inherited from [Noun](/business/nouns/noun). | None. | `Contact.updated` | Two-way: `try`, `send`, `do` | | [Contact.delete](/business/nouns/contact/delete) | Deletes a Contact; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Contact.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Contact.create` | Yes | Yes | Yes | No | | `Contact.get` | Yes | Yes | Yes | Yes | | `Contact.list` | Yes | Yes | Yes | Yes | | `Contact.update` | Yes | Yes | Yes | No | | `Contact.delete` | Yes | Yes | Yes | No | | `Contact.enrich` | Yes | Yes | Yes | No | | `Contact.enroll` | Yes | Yes | Yes | No | | `Contact.merge` | Yes | No | No | No | | `Contact.subscribe` | Yes | Yes | Yes | No | | `Contact.suppress` | Yes | Yes | Yes | No | | `Contact.unsubscribe` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Enroll the contact Malik Owens with a sequence. ``` **API** ```bash curl -X POST https://api.sb/tutorloop.com/contacts/contact_1/enroll \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"sequence":"sequence_1"}' ``` ```json { "api": "https://api.sb/tutorloop.com", "contact": { "$id": "https://api.sb/tutorloop.com/contacts/contact_1", "$type": "Contact", "email": "malik@tutorloop.com", "phone": "Example phone" }, "enrollment": { "$id": "https://api.sb/tutorloop.com/enrollments/enrollment_1", "$type": "Enrollment", "status": "active", "step": "Example step" }, "action": { "$id": "https://api.sb/tutorloop.com/actions/action_1", "operation": "Contact.enroll", "status": "done" }, "links": { "self": "https://api.sb/tutorloop.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { contact, enrollment } = await $.Contact.enroll({ contact: 'contact_1', sequence: 'sequence_1' }) ``` **CLI** ```bash npx startup-builder do Contact.enroll --json '{"contact":"contact_1","sequence":"sequence_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Contact.enroll({ contact: 'contact_1', sequence: 'sequence_1' })" } } ``` ## Example `owner@brightsmiles.dental` books a demo of a dental-scheduling [App](/business/nouns/app) and becomes a Contact. She has not given marketing [Consent](/business/nouns/consent), so she gets replies about her demo but no newsletter. # merge URL: /business/nouns/contact/merge · Id: `verb:Contact.merge` · Call: `await $.Contact.merge({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Merge joins a duplicate Contact into another, keeping every link, Message and Event on the one that remains. Merge joins a duplicate [Contact](/business/nouns/contact) into another, keeping every link, [Message](/business/nouns/message) and [Event](/business/nouns/event) on the one that remains. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `contact` | [Contact](/business/nouns/contact) | Yes | The duplicate. | | `into` | [Contact](/business/nouns/contact) | Yes | The Contact that remains. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `contact` | [Contact](/business/nouns/contact) | Yes | The remaining Contact. | ## Effects - Emits [`Contact.merged`](/business/events/Contact.merged). - Performed by the [Sales Lead](/agents/sales/sales-lead). - One-way: it waits out its delay window, and runs in the `send` and `do` modes. - Keeps the merged id as an alias; nothing is deleted. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Contact.merge](/business/nouns/contact/merge) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Medium: one-way, bounded | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | 1 business hour, in which a watcher can pause, redirect or cancel it; then it runs. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Merge the contact Lena Fischer. ``` **API** ```bash curl -X POST https://api.sb/petpantry.shop/contacts/contact_1/merge \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"into":"contact_1"}' ``` ```json { "api": "https://api.sb/petpantry.shop", "contact": { "$id": "https://api.sb/petpantry.shop/contacts/contact_1", "$type": "Contact", "email": "lena@petpantry.shop", "phone": "Example phone" }, "action": { "$id": "https://api.sb/petpantry.shop/actions/action_1", "operation": "Contact.merge", "status": "done" }, "links": { "self": "https://api.sb/petpantry.shop/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const contact = await $.Contact.merge({ contact: 'contact_1', into: 'contact_1' }) ``` **CLI** ```bash npx startup-builder do Contact.merge --json '{"contact":"contact_1","into":"contact_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Contact.merge({ contact: 'contact_1', into: 'contact_1' })" } } ``` # subscribe URL: /business/nouns/contact/subscribe · Id: `verb:Contact.subscribe` · Call: `await $.Contact.subscribe({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Subscribe records a Contact’s chosen topics and frequency from the hosted preference page, with Consent for each topic. Subscribe records a [Contact](/business/nouns/contact)’s chosen topics and frequency from the hosted preference page, with [Consent](/business/nouns/consent) for each topic. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `contact` | [Contact](/business/nouns/contact) | Yes | The Contact. | | `topics` | `string[]` | Yes | The topics the Contact chose. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `contact` | [Contact](/business/nouns/contact) | Yes | The Contact, with their topics. | ## Effects - Emits [`Contact.subscribed`](/business/events/Contact.subscribed). - Performed by the [Marketing Lead](/agents/marketing/marketing-lead). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Writes one Consent per topic, with its notice and time. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Contact.subscribe](/business/nouns/contact/subscribe) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Subscribe the contact Tomas Berg. ``` **API** ```bash curl -X POST https://api.sb/kilnbakery.com/contacts/contact_1/subscribe \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"topics":["Example topics"]}' ``` ```json { "api": "https://api.sb/kilnbakery.com", "contact": { "$id": "https://api.sb/kilnbakery.com/contacts/contact_1", "$type": "Contact", "email": "tomas@kilnbakery.com", "phone": "Example phone" }, "action": { "$id": "https://api.sb/kilnbakery.com/actions/action_1", "operation": "Contact.subscribe", "status": "done" }, "links": { "self": "https://api.sb/kilnbakery.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const contact = await $.Contact.subscribe({ contact: 'contact_1', topics: ['Example topics'] }) ``` **CLI** ```bash npx startup-builder do Contact.subscribe --json '{"contact":"contact_1","topics":["Example topics"]}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Contact.subscribe({ contact: 'contact_1', topics: ['Example topics'] })" } } ``` # suppress URL: /business/nouns/contact/suppress · Id: `verb:Contact.suppress` · Call: `await $.Contact.suppress({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Suppress records a Suppression for a Contact’s address, which every Startup honors forever. Suppress records a [Suppression](/business/nouns/suppression) for a [Contact](/business/nouns/contact)’s address, which every [Startup](/business/nouns/startup) honors forever. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `contact` | [Contact](/business/nouns/contact) | Yes | The Contact who opts out. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `contact` | [Contact](/business/nouns/contact) | Yes | The suppressed Contact. | ## Effects - Emits [`Contact.suppressed`](/business/events/Contact.suppressed). - Performed by the [Prospector](/agents/sales/prospector). - Ends every Sequence the Contact is in. - Keeps the record: suppression is a row, never a delete. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Contact.suppress](/business/nouns/contact/suppress) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Suppress the contact Rosa Ibarra. ``` **API** ```bash curl -X POST https://api.sb/patentpad.com/contacts/contact_1/suppress \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/patentpad.com", "contact": { "$id": "https://api.sb/patentpad.com/contacts/contact_1", "$type": "Contact", "email": "rosa@patentpad.com", "phone": "Example phone" }, "action": { "$id": "https://api.sb/patentpad.com/actions/action_1", "operation": "Contact.suppress", "status": "done" }, "links": { "self": "https://api.sb/patentpad.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const contact = await $.Contact.suppress({ contact: 'contact_1' }) ``` **CLI** ```bash npx startup-builder do Contact.suppress --json '{"contact":"contact_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Contact.suppress({ contact: 'contact_1' })" } } ``` # unsubscribe URL: /business/nouns/contact/unsubscribe · Id: `verb:Contact.unsubscribe` · Call: `await $.Contact.unsubscribe({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Unsubscribe stops commercial Messages to a Contact in one click, for one topic or all, honored at once. Unsubscribe stops commercial [Messages](/business/nouns/message) to a [Contact](/business/nouns/contact) in one click, for one topic or all, honored at once. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `contact` | [Contact](/business/nouns/contact) | Yes | The Contact. | | `topic` | `string` | No | One topic; omitted, every commercial topic. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `contact` | [Contact](/business/nouns/contact) | Yes | The Contact, unsubscribed. | ## Effects - Emits [`Contact.unsubscribed`](/business/events/Contact.unsubscribed). - Performed by the [Marketing Lead](/agents/marketing/marketing-lead). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Writes a Suppression when no topic is named. - Never asks for sign-in or confirmation, and never waits. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Contact.unsubscribe](/business/nouns/contact/unsubscribe) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Unsubscribe the contact Rosa Ibarra. ``` **API** ```bash curl -X POST https://api.sb/patentpad.com/contacts/contact_1/unsubscribe \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/patentpad.com", "contact": { "$id": "https://api.sb/patentpad.com/contacts/contact_1", "$type": "Contact", "email": "rosa@patentpad.com", "phone": "Example phone" }, "action": { "$id": "https://api.sb/patentpad.com/actions/action_1", "operation": "Contact.unsubscribe", "status": "done" }, "links": { "self": "https://api.sb/patentpad.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const contact = await $.Contact.unsubscribe({ contact: 'contact_1' }) ``` **CLI** ```bash npx startup-builder do Contact.unsubscribe --json '{"contact":"contact_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Contact.unsubscribe({ contact: 'contact_1' })" } } ``` # draft URL: /business/nouns/content/draft · Id: `verb:Content.draft` · Call: `await $.Content.draft({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Draft writes Content of one kind from a brief, such as an article for a question the help center could not answer. Draft writes [Content](/business/nouns/content) of one kind from a brief, such as an article for a question the help center could not answer. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `kind` | `string` | Yes | What to write. | | `brief` | `text` | Yes | The question or brief it answers. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `content` | [Content](/business/nouns/content) | Yes | The draft. | ## Effects - Emits [`Content.drafted`](/business/events/Content.drafted). - Performed by the [Content Lead](/agents/marketing/content-lead). - Two-way: it runs at once, in the `try`, `send` and `do` modes. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Content.draft](/business/nouns/content/draft) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Draft the latest content. ``` **API** ```bash curl -X POST https://api.sb/quietcopy.com/content/draft \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"kind":"article","brief":"Example brief"}' ``` ```json { "api": "https://api.sb/quietcopy.com", "content": { "$id": "https://api.sb/quietcopy.com/content/content_1", "$type": "Content", "title": "Résumé review" }, "action": { "$id": "https://api.sb/quietcopy.com/actions/action_1", "operation": "Content.draft", "status": "done" }, "links": { "self": "https://api.sb/quietcopy.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const content = await $.Content.draft({ kind: 'article', brief: 'Example brief' }) ``` **CLI** ```bash npx startup-builder do Content.draft --json '{"kind":"article","brief":"Example brief"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Content.draft({ kind: 'article', brief: 'Example brief' })" } } ``` # Content URL: /business/nouns/content · Id: `noun:content` > Content is authored material with a draft and a published state, such as a post, an article, or a changelog entry. Content is authored material with a draft and a published state, such as a post, an article, or a changelog entry. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `title` | `string` | Yes | The headline. | | `publishedAt` | `datetime` | No | When it went live. | | `kind` | `string` | No | What the Content is, so each System reads its own kind. | ## Object ```json { "$id": "https://api.sb/ledgerlark.com/content/content_1", "$type": "Content", "title": "Monthly close", "publishedAt": "2026-10-22T12:00:00Z", "kind": "article" } ``` ## Relationships - A Content **is displayed on** many [Pages](/business/nouns/page): [Pages](/business/nouns/page) display published Content; one piece appears on many Pages. `displayedOn`, inverse [`displays`](/business/nouns/page#rel-displays). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Content.draft](/business/nouns/content/draft) | Draft writes Content of one kind from a brief, such as an article for a question the help center could not answer. | [Content Lead](/agents/marketing/content-lead) | [`Content.drafted`](/business/events/Content.drafted) | Two-way: `try`, `send`, `do` | | [Content.publish](/business/nouns/content/publish) | Publish puts a Content draft live on its Site and every Interface, once it passes the Evals for its kind. | [Content Lead](/agents/marketing/content-lead) | [`Content.published`](/business/events/Content.published) | One-way (brand): `send`, `do` | | [Content.create](/business/nouns/content/create) | Creates a Content. Inherited from [Noun](/business/nouns/noun). | None. | `Content.created` | Two-way: `try`, `send`, `do` | | [Content.get](/business/nouns/content/get) | Returns one Content by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Content.list](/business/nouns/content/list) | Returns Content, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Content.update](/business/nouns/content/update) | Changes the given properties of a Content. Inherited from [Noun](/business/nouns/noun). | None. | `Content.updated` | Two-way: `try`, `send`, `do` | | [Content.delete](/business/nouns/content/delete) | Deletes a Content; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Content.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Content.create` | Yes | Yes | Yes | No | | `Content.get` | Yes | Yes | Yes | Yes | | `Content.list` | Yes | Yes | Yes | Yes | | `Content.update` | Yes | Yes | Yes | No | | `Content.delete` | Yes | Yes | Yes | No | | `Content.draft` | Yes | Yes | Yes | No | | `Content.publish` | Yes | No | No | No | ## Call it **Ask** ```text Draft the latest content. ``` **API** ```bash curl -X POST https://api.sb/quietcopy.com/content/draft \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"kind":"article","brief":"Example brief"}' ``` ```json { "api": "https://api.sb/quietcopy.com", "content": { "$id": "https://api.sb/quietcopy.com/content/content_1", "$type": "Content", "title": "Résumé review" }, "action": { "$id": "https://api.sb/quietcopy.com/actions/action_1", "operation": "Content.draft", "status": "done" }, "links": { "self": "https://api.sb/quietcopy.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const content = await $.Content.draft({ kind: 'article', brief: 'Example brief' }) ``` **CLI** ```bash npx startup-builder do Content.draft --json '{"kind":"article","brief":"Example brief"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Content.draft({ kind: 'article', brief: 'Example brief' })" } } ``` ## Example A release note for the bulk-export button of a bookkeeping [SaaS](/products/templates/saas) is Content: drafted by the [Product Lead](/agents/product/product-lead), reviewed, then published to the changelog [Page](/business/nouns/page). # publish URL: /business/nouns/content/publish · Id: `verb:Content.publish` · Call: `await $.Content.publish({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Publish puts a Content draft live on its Site and every Interface, once it passes the Evals for its kind. Publish puts a [Content](/business/nouns/content) draft live on its [Site](/business/nouns/site) and every [Interface](/business/nouns/interface), once it passes the Evals for its kind. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `content` | [Content](/business/nouns/content) | Yes | The draft to publish. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `content` | [Content](/business/nouns/content) | Yes | The published Content. | ## Effects - Emits [`Content.published`](/business/events/Content.published). - Performed by the [Content Lead](/agents/marketing/content-lead). - One-way (brand): it waits out its delay window, and runs in the `send` and `do` modes. - Agents read it as Markdown; people read it in each locale the Site serves. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Content.publish](/business/nouns/content/publish) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Medium: one-way, bounded (brand) | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | 1 business hour, in which a watcher can pause, redirect or cancel it; then it runs. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Publish the latest content. ``` **API** ```bash curl -X POST https://api.sb/quietcopy.com/content/content_1/publish \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/quietcopy.com", "content": { "$id": "https://api.sb/quietcopy.com/content/content_1", "$type": "Content", "title": "Résumé review" }, "action": { "$id": "https://api.sb/quietcopy.com/actions/action_1", "operation": "Content.publish", "status": "done" }, "links": { "self": "https://api.sb/quietcopy.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const content = await $.Content.publish({ content: 'content_1' }) ``` **CLI** ```bash npx startup-builder do Content.publish --json '{"content":"content_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Content.publish({ content: 'content_1' })" } } ``` # Control URL: /business/nouns/control · Id: `noun:control` > A Control is a rule the platform enforces on every write it covers, with a test that runs over the whole population. A Control is a rule the platform enforces on every write it covers, with a test that runs over the whole population. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `objective` | `text` | Yes | What the Control prevents or detects, in one sentence. | | `kind` | `string` | Yes | One of `preventive` (stops the failure) or `detective` (finds it). | | `inheritance` | `string` | Yes | One of `inherited`, `shared`, or `owned`, resolved per namespace from the platform down. | | `criteria` | list of [Criterion](/business/nouns/criterion) | Yes | The framework Criteria the Control satisfies. | | `test` | `json` | Yes | An Event selector and the assertion every selected Event must pass. | | `wakes` | `text` | No | The conditions that add the Control to a Startup’s own floor, such as a first Human Worker. | ## Object ```json { "$id": "https://api.sb/shiftnote.app/controls/control_1", "$type": "Control", "objective": "Example objective", "kind": "Example kind", "inheritance": "inherited", "criteria": [ "criterion_1" ], "test": {}, "wakes": "Example wakes" } ``` ## Relationships - A Control **proven by** many [Proofs](/business/nouns/proof): the Control whose test the [Proof](/business/nouns/proof) records running over a range of [Events](/business/nouns/event). `provenBy`, inverse [`proves`](/business/nouns/proof#rel-proves). - A Control **treats** many [Risks](/business/nouns/risk): the Controls that lower the [Risk](/business/nouns/risk). Every Control cites the Risks it treats. `treats`, inverse [`treatedBy`](/business/nouns/risk#rel-treated-by). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Control.get](/business/nouns/control/get) | Returns one Control by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Control.list](/business/nouns/control/list) | Returns Controls, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | A Control is kept forever and never edited: it has no `update` or `delete`. ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Control.get` | Yes | Yes | Yes | Yes | | `Control.list` | Yes | Yes | Yes | Yes | ## Call it **Ask** ```text Show me the latest control. ``` **API** ```bash curl https://api.sb/routewise.dev/controls/control_1 \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/routewise.dev", "$type": "Control", "$id": "https://api.sb/routewise.dev/controls/control_1", "control": { "$id": "https://api.sb/routewise.dev/controls/control_1", "$type": "Control", "objective": "Example objective", "kind": "Example kind", "inheritance": "inherited", "criteria": [ "criterion_1" ] }, "links": { "self": "https://api.sb/routewise.dev/controls/control_1", "up": "https://api.sb/routewise.dev/controls" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const control = await $.Control.get({ id: 'control_1' }) ``` **CLI** ```bash npx startup-builder do Control.get --json '{"id":"control_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Control.get({ id: 'control_1' })" } } ``` ## Example [Change approval](/systems/trust-and-governance/controls/change-approval) selects every merged [Change](/business/nouns/change) to a definition and asserts that a [Decision](/business/nouns/decision) approved it, by an approver other than the author. It is `inherited`: no [Startup](/business/nouns/startup) can loosen it. # answer URL: /business/nouns/conversation/answer · Id: `verb:Conversation.answer` · Call: `await $.Conversation.answer({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Answer replies in a Conversation through the Channel it arrived on and closes the reply Task it opened. Answer replies in a [Conversation](/business/nouns/conversation) through the [Channel](/business/nouns/channel) it arrived on and closes the reply [Task](/business/nouns/task) it opened. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `conversation` | [Conversation](/business/nouns/conversation) | Yes | The Conversation that waits. | | `body` | `text` | Yes | The reply. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `conversation` | [Conversation](/business/nouns/conversation) | Yes | The answered Conversation. | ## Effects - Emits [`Conversation.answered`](/business/events/Conversation.answered). - Performed by the [Customer Lead](/agents/customer/customer-lead). - Runs the reply through every Guard before it leaves. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Conversation.answer](/business/nouns/conversation/answer) | | The record is not in a state that allows this Verb, so the call is refused. | [`refused`](/code/api/errors/refused) | Read the record, run the Verb that moves it to an allowed state, then retry. | [Conversation.answer](/business/nouns/conversation/answer) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Answer the latest conversation. ``` **API** ```bash curl -X POST https://api.sb/ledgerlark.com/conversations/conversation_1/answer \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"body":"Example body"}' ``` ```json { "api": "https://api.sb/ledgerlark.com", "conversation": { "$id": "https://api.sb/ledgerlark.com/conversations/conversation_1", "$type": "Conversation", "subject": "Example subject", "answeredAt": "2026-10-22T12:00:00Z" }, "action": { "$id": "https://api.sb/ledgerlark.com/actions/action_1", "operation": "Conversation.answer", "status": "done" }, "links": { "self": "https://api.sb/ledgerlark.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const conversation = await $.Conversation.answer({ conversation: 'conversation_1', body: 'Example body' }) ``` **CLI** ```bash npx startup-builder do Conversation.answer --json '{"conversation":"conversation_1","body":"Example body"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Conversation.answer({ conversation: 'conversation_1', body: 'Example body' })" } } ``` # assign URL: /business/nouns/conversation/assign · Id: `verb:Conversation.assign` · Call: `await $.Conversation.assign({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Assign routes a Conversation to the Worker holding the right Role, by topic, Customer tier and language. Assign routes a [Conversation](/business/nouns/conversation) to the [Worker](/business/nouns/worker) holding the right [Role](/business/nouns/role), by topic, [Customer](/business/nouns/customer) tier and language. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `conversation` | [Conversation](/business/nouns/conversation) | Yes | The Conversation to route. | | `worker` | [Worker](/business/nouns/worker) | No | The Worker to take it; omitted, the routing Policy picks. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `conversation` | [Conversation](/business/nouns/conversation) | Yes | The Conversation, with its Worker. | ## Effects - Emits [`Conversation.assigned`](/business/events/Conversation.assigned). - Performed by the [Customer Lead](/agents/customer/customer-lead). - Two-way: it runs at once, in the `try`, `send` and `do` modes. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Conversation.assign](/business/nouns/conversation/assign) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Assign the latest conversation. ``` **API** ```bash curl -X POST https://api.sb/kilnbakery.com/conversations/conversation_1/assign \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/kilnbakery.com", "conversation": { "$id": "https://api.sb/kilnbakery.com/conversations/conversation_1", "$type": "Conversation", "subject": "Example subject", "answeredAt": "2026-10-22T12:00:00Z" }, "action": { "$id": "https://api.sb/kilnbakery.com/actions/action_1", "operation": "Conversation.assign", "status": "done" }, "links": { "self": "https://api.sb/kilnbakery.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const conversation = await $.Conversation.assign({ conversation: 'conversation_1' }) ``` **CLI** ```bash npx startup-builder do Conversation.assign --json '{"conversation":"conversation_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Conversation.assign({ conversation: 'conversation_1' })" } } ``` # close URL: /business/nouns/conversation/close · Id: `verb:Conversation.close` · Call: `await $.Conversation.close({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Close marks a Conversation resolved, confirmed by the Customer or assumed after 72 hours with no reply. Close marks a [Conversation](/business/nouns/conversation) resolved, confirmed by the [Customer](/business/nouns/customer) or assumed after 72 hours with no reply. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `conversation` | [Conversation](/business/nouns/conversation) | Yes | The answered Conversation. | | `resolution` | `string` | Yes | How it ended: the Customer said so, or 72 hours passed after an answer with no reply. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `conversation` | [Conversation](/business/nouns/conversation) | Yes | The Conversation, resolved. | ## Effects - Emits [`Conversation.closed`](/business/events/Conversation.closed). - Performed by the [Customer Lead](/agents/customer/customer-lead). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Reverses through `reopen` within 7 days on any of four signals from the Customer. - Keeps the close Event when a resolution reverses; nothing is deleted. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Conversation.close](/business/nouns/conversation/close) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Close the latest conversation. ``` **API** ```bash curl -X POST https://api.sb/routewise.dev/conversations/conversation_1/close \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"resolution":"confirmed"}' ``` ```json { "api": "https://api.sb/routewise.dev", "conversation": { "$id": "https://api.sb/routewise.dev/conversations/conversation_1", "$type": "Conversation", "subject": "Example subject", "answeredAt": "2026-10-22T12:00:00Z" }, "action": { "$id": "https://api.sb/routewise.dev/actions/action_1", "operation": "Conversation.close", "status": "done" }, "links": { "self": "https://api.sb/routewise.dev/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const conversation = await $.Conversation.close({ conversation: 'conversation_1', resolution: 'confirmed' }) ``` **CLI** ```bash npx startup-builder do Conversation.close --json '{"conversation":"conversation_1","resolution":"confirmed"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Conversation.close({ conversation: 'conversation_1', resolution: 'confirmed' })" } } ``` # escalate URL: /business/nouns/conversation/escalate · Id: `verb:Conversation.escalate` · Call: `await $.Conversation.escalate({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Escalate hands a Conversation and its summary to the Worker in the Role above, a Human only where one holds it. Escalate hands a [Conversation](/business/nouns/conversation) and its summary to the [Worker](/business/nouns/worker) in the [Role](/business/nouns/role) above, a [Human](/business/nouns/human) only where one holds it. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `conversation` | [Conversation](/business/nouns/conversation) | Yes | The Conversation to hand off. | | `reason` | `string` | Yes | Why it moves up. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `conversation` | [Conversation](/business/nouns/conversation) | Yes | The Conversation, with its new Worker. | ## Effects - Emits [`Conversation.escalated`](/business/events/Conversation.escalated). - Performed by the [Customer Lead](/agents/customer/customer-lead). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - A refund over a Limit is an Approval, not an escalation. - A Customer who asks for a person reaches one wherever the operating model staffs one. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Conversation.escalate](/business/nouns/conversation/escalate) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Escalate the latest conversation. ``` **API** ```bash curl -X POST https://api.sb/patentpad.com/conversations/conversation_1/escalate \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"reason":"lowConfidence"}' ``` ```json { "api": "https://api.sb/patentpad.com", "conversation": { "$id": "https://api.sb/patentpad.com/conversations/conversation_1", "$type": "Conversation", "subject": "Example subject", "answeredAt": "2026-10-22T12:00:00Z" }, "action": { "$id": "https://api.sb/patentpad.com/actions/action_1", "operation": "Conversation.escalate", "status": "done" }, "links": { "self": "https://api.sb/patentpad.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const conversation = await $.Conversation.escalate({ conversation: 'conversation_1', reason: 'lowConfidence' }) ``` **CLI** ```bash npx startup-builder do Conversation.escalate --json '{"conversation":"conversation_1","reason":"lowConfidence"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Conversation.escalate({ conversation: 'conversation_1', reason: 'lowConfidence' })" } } ``` # Conversation URL: /business/nouns/conversation · Id: `noun:conversation` > A Conversation is a Thread with one or more Contacts that a Worker must answer, such as a support request. A Conversation is a [Thread](/business/nouns/thread) with one or more [Contacts](/business/nouns/contact) that a [Worker](/business/nouns/worker) must answer, such as a support request. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `answeredAt` | `datetime` | No | When a Worker last answered. | | `firstAnsweredAt` | `datetime` | No | When a Worker first answered; set once, never overwritten. `answeredAt` keeps the last answer. | | `respondBy` | `datetime` | No | When the first answer is due: Setting `support.firstResponseWithin` per Offer, default 4 business hours. | | `status` | `string` | No | Open, waiting on the Customer, or resolved; computed from its answers, closes and reopens. | | `resolvedAt` | `datetime` | No | When it was resolved; empty again when the resolution reverses. | | `resolution` | `string` | No | How it was resolved: the Customer said so, or 72 hours passed after an answer with no reply. |
Inherited from [Thread](/business/nouns/thread): 1 property | Property | Type | Required | Description | | --- | --- | --- | --- | | `subject` | `string` | No | What the Thread is about. |
## Object ```json { "$id": "https://api.sb/shiftnote.app/conversations/conversation_1", "$type": "Conversation", "subject": "Example subject", "answeredAt": "2026-10-22T12:00:00Z", "firstAnsweredAt": "2026-10-22T12:00:00Z", "respondBy": "2026-10-22T12:00:00Z", "status": "open", "resolvedAt": "2026-10-22T12:00:00Z", "resolution": "confirmed" } ``` ## Relationships - A Conversation **awaits** one [Worker](/business/nouns/worker): one [Worker](/business/nouns/worker) owes each Conversation its next answer. `awaits`, inverse [`conversations`](/business/nouns/worker#rel-conversations). - A Conversation **has** one [Customer](/business/nouns/customer): the [Customer](/business/nouns/customer) a Conversation serves, so every answer reads that Customer’s records. `customer`, inverse [`opens`](/business/nouns/customer#rel-opens). - A Conversation **raises** many [Threads](/business/nouns/thread): the intake [Threads](/business/nouns/thread) a support Conversation opens, each deadline counted from the Conversation’s first [Message](/business/nouns/message). `raises`, inverse [`raisedIn`](/business/nouns/thread#rel-raised-in). - A Conversation **reports** one [Issue](/business/nouns/issue): the [Issue](/business/nouns/issue) or [Incident](/business/nouns/incident) a Conversation reports; resolving it answers every linked Conversation. `reports`, inverse [`conversations`](/business/nouns/issue#rel-conversations). ## Lifecycle | State | Meaning | Moves to | | --- | --- | --- | | `open` (first) | A Contact wrote, and a Worker owes the answer by `respondBy`. | `waiting` on [`Conversation.answered`](/business/events/Conversation.answered); `waiting` on [`Action.asked`](/business/events/Action.asked) when the Question goes to this Conversation’s Contact; `resolved` on [`Conversation.closed`](/business/events/Conversation.closed) | | `waiting` | A Worker answered, and the Customer owes the reply. | `open` on `Message.created` when a Contact’s Message arrives in this Conversation; `resolved` on [`Conversation.closed`](/business/events/Conversation.closed) | | `resolved` | Resolved, confirmed by the Customer or assumed after 72 hours with no reply. | `open` on [`Conversation.reopened`](/business/events/Conversation.reopened) | ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Conversation.answer](/business/nouns/conversation/answer) | Answer replies in a Conversation through the Channel it arrived on and closes the reply Task it opened. | [Customer Lead](/agents/customer/customer-lead) | [`Conversation.answered`](/business/events/Conversation.answered) | None. | | [Conversation.assign](/business/nouns/conversation/assign) | Assign routes a Conversation to the Worker holding the right Role, by topic, Customer tier and language. | [Customer Lead](/agents/customer/customer-lead) | [`Conversation.assigned`](/business/events/Conversation.assigned) | Two-way: `try`, `send`, `do` | | [Conversation.close](/business/nouns/conversation/close) | Close marks a Conversation resolved, confirmed by the Customer or assumed after 72 hours with no reply. | [Customer Lead](/agents/customer/customer-lead) | [`Conversation.closed`](/business/events/Conversation.closed) | Two-way: `try`, `send`, `do` | | [Conversation.escalate](/business/nouns/conversation/escalate) | Escalate hands a Conversation and its summary to the Worker in the Role above, a Human only where one holds it. | [Customer Lead](/agents/customer/customer-lead) | [`Conversation.escalated`](/business/events/Conversation.escalated) | Two-way: `try`, `send`, `do` | | [Conversation.reopen](/business/nouns/conversation/reopen) | Reopen reverses a Conversation’s resolution when a reversal signal arrives within 7 days, and grades the resolution a failure. | [Customer Lead](/agents/customer/customer-lead) | [`Conversation.reopened`](/business/events/Conversation.reopened) | Two-way: `try`, `send`, `do` | | [Conversation.create](/business/nouns/conversation/create) | Creates a Conversation. Inherited from [Noun](/business/nouns/noun). | None. | `Conversation.created` | Two-way: `try`, `send`, `do` | | [Conversation.get](/business/nouns/conversation/get) | Returns one Conversation by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Conversation.list](/business/nouns/conversation/list) | Returns Conversations, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Conversation.update](/business/nouns/conversation/update) | Changes the given properties of a Conversation. Inherited from [Noun](/business/nouns/noun). | None. | `Conversation.updated` | Two-way: `try`, `send`, `do` | | [Conversation.delete](/business/nouns/conversation/delete) | Deletes a Conversation; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Conversation.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Conversation.create` | Yes | Yes | Yes | No | | `Conversation.get` | Yes | Yes | Yes | Yes | | `Conversation.list` | Yes | Yes | Yes | Yes | | `Conversation.update` | Yes | Yes | Yes | No | | `Conversation.delete` | Yes | Yes | Yes | No | | `Conversation.answer` | Yes | Yes | Yes | No | | `Conversation.assign` | Yes | Yes | Yes | No | | `Conversation.close` | Yes | Yes | Yes | No | | `Conversation.escalate` | Yes | Yes | Yes | No | | `Conversation.reopen` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Answer the latest conversation. ``` **API** ```bash curl -X POST https://api.sb/ledgerlark.com/conversations/conversation_1/answer \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"body":"Example body"}' ``` ```json { "api": "https://api.sb/ledgerlark.com", "conversation": { "$id": "https://api.sb/ledgerlark.com/conversations/conversation_1", "$type": "Conversation", "subject": "Example subject", "answeredAt": "2026-10-22T12:00:00Z" }, "action": { "$id": "https://api.sb/ledgerlark.com/actions/action_1", "operation": "Conversation.answer", "status": "done" }, "links": { "self": "https://api.sb/ledgerlark.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const conversation = await $.Conversation.answer({ conversation: 'conversation_1', body: 'Example body' }) ``` **CLI** ```bash npx startup-builder do Conversation.answer --json '{"conversation":"conversation_1","body":"Example body"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Conversation.answer({ conversation: 'conversation_1', body: 'Example body' })" } } ``` ## Example A [Customer](/business/nouns/customer) emails "my API key stopped working." The Conversation stays open until the support [Agent](/business/nouns/agent) answers and the Customer confirms the fix. # reopen URL: /business/nouns/conversation/reopen · Id: `verb:Conversation.reopen` · Call: `await $.Conversation.reopen({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Reopen reverses a Conversation’s resolution when a reversal signal arrives within 7 days, and grades the resolution a failure. Reopen reverses a [Conversation](/business/nouns/conversation)’s resolution when a reversal signal arrives within 7 days, and grades the resolution a failure. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `conversation` | [Conversation](/business/nouns/conversation) | Yes | The resolved Conversation. | | `signal` | `string` | Yes | What reversed it: a new Message on the subject, a request for a person, a rating of 2 or lower, or a Dispute. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `conversation` | [Conversation](/business/nouns/conversation) | Yes | The Conversation, open again. | ## Effects - Emits [`Conversation.reopened`](/business/events/Conversation.reopened). - Performed by the [Customer Lead](/agents/customer/customer-lead). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Records a failed Evaluator verdict on the Worker that resolved it. - Adds the reversal as a test case that the Customer Lead’s next Version passes before it ships. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Conversation.reopen](/business/nouns/conversation/reopen) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Reopen the latest conversation. ``` **API** ```bash curl -X POST https://api.sb/petpantry.shop/conversations/conversation_1/reopen \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"signal":"askedForPerson"}' ``` ```json { "api": "https://api.sb/petpantry.shop", "conversation": { "$id": "https://api.sb/petpantry.shop/conversations/conversation_1", "$type": "Conversation", "subject": "Example subject", "answeredAt": "2026-10-22T12:00:00Z" }, "action": { "$id": "https://api.sb/petpantry.shop/actions/action_1", "operation": "Conversation.reopen", "status": "done" }, "links": { "self": "https://api.sb/petpantry.shop/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const conversation = await $.Conversation.reopen({ conversation: 'conversation_1', signal: 'askedForPerson' }) ``` **CLI** ```bash npx startup-builder do Conversation.reopen --json '{"conversation":"conversation_1","signal":"askedForPerson"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Conversation.reopen({ conversation: 'conversation_1', signal: 'askedForPerson' })" } } ``` # Cost URL: /business/nouns/cost · Id: `noun:cost` > A Cost is an Entry against a cost account that an Action causes, posted to the Startup the Action ran in. A Cost is an [Entry](/business/nouns/entry) against a cost account that an [Action](/business/nouns/action) causes, posted to the [Startup](/business/nouns/startup) the Action ran in. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `action` | [Action](/business/nouns/action) | Yes | The Action that caused it. | | `startup` | [Startup](/business/nouns/startup) | Yes | The Startup it is posted to. | | `kind` | `string` | Yes | One of `model`, `upstream`, `human`, `platform` or `shared`. | | `allocation` | `text` | No | For shared Cost, the stated rule that splits it across Startups. | | `attempt` | `integer` | No | Which outside attempt this Cost paid for when one call tried several upstreams in rank. | | `overrun` | `money` | No | How far the settled amount exceeded the Action’s reservation; an overrun past a Limit opens an Approval. |
Inherited from [Entry](/business/nouns/entry): 4 properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `account` | `string` | Yes | The code of the account in the chart of accounts, such as revenue or cash. | | `amount` | `money` | Yes | The amount and currency. | | `direction` | `string` | Yes | One of `debit` or `credit`. | | `counterparty` | [Startup](/business/nouns/startup) | No | The sibling Startup on the other side of an intercompany Entry; empty for outside parties. |
## Object ```json { "$id": "https://api.sb/patentpad.com/costs/cost_1", "$type": "Cost", "account": "cash", "amount": { "amount": 499, "currency": "USD" }, "direction": "debit", "counterparty": "startup_1", "action": "action_1", "startup": "startup_1", "kind": "model", "allocation": "Split by each Startup’s share of API calls", "attempt": 1, "overrun": { "amount": 499, "currency": "USD" } } ``` ## Relationships - A Cost **is posted by** one [Action](/business/nouns/action): every Cost an [Action](/business/nouns/action) causes posts to the [Startup](/business/nouns/startup) it ran in, so each Startup’s P&L is complete. `postedBy`, inverse [`posts`](/business/nouns/action#rel-posts). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Cost.get](/business/nouns/cost/get) | Returns one Cost by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Cost.list](/business/nouns/cost/list) | Returns Costs, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | A Cost is kept forever and never edited: it has no `update` or `delete`. ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Cost.get` | Yes | Yes | Yes | Yes | | `Cost.list` | Yes | Yes | Yes | Yes | ## Call it **Ask** ```text Show me the latest cost. ``` **API** ```bash curl https://api.sb/shiftnote.app/costs/cost_1 \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/shiftnote.app", "$type": "Cost", "$id": "https://api.sb/shiftnote.app/costs/cost_1", "cost": { "$id": "https://api.sb/shiftnote.app/costs/cost_1", "$type": "Cost", "account": "cash", "amount": { "amount": 79, "currency": "USD" }, "direction": "debit", "action": "action_1" }, "links": { "self": "https://api.sb/shiftnote.app/costs/cost_1", "up": "https://api.sb/shiftnote.app/costs" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const cost = await $.Cost.get({ id: 'cost_1' }) ``` **CLI** ```bash npx startup-builder do Cost.get --json '{"id":"cost_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Cost.get({ id: 'cost_1' })" } } ``` ## Example A permit-status API pays $0.40 for each county records request. Each one is a Cost on the lookup Action, so the margin on a $1 lookup reads $0.60. # Coupon URL: /business/nouns/coupon · Id: `noun:coupon` > A Coupon is a discount on Offers, by amount or percent, for one charge, several months or every charge, limited by date and redemptions. A Coupon is a discount on [Offers](/business/nouns/offer), by amount or percent, for one charge, several months or every charge, limited by date and redemptions. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `percentOff` | `number` | No | The percent taken off each charge it applies to; set this or `amountOff`. Never randomized. | | `amountOff` | `money` | No | The fixed amount taken off each charge it applies to. Never randomized. | | `duration` | `string` | Yes | How long it applies: `once`, `repeating` for `months`, or `forever`. | | `months` | `integer` | No | How many months a `repeating` Coupon applies. | | `code` | `string` | No | The promotion code a buyer types at checkout, when the Coupon has one. | | `redeemBy` | `datetime` | No | The last moment it can be redeemed. | | `maxRedemptions` | `integer` | No | How many times it can be redeemed across all Customers. | ## Object ```json { "$id": "https://api.sb/tutorloop.com/coupons/coupon_1", "$type": "Coupon", "percentOff": 1, "amountOff": { "amount": 60, "currency": "USD" }, "duration": "once", "months": 1, "code": "LAUNCH20", "redeemBy": "2026-10-22T12:00:00Z", "maxRedemptions": 1 } ``` ## Relationships - A Coupon **discounts** many [Offers](/business/nouns/offer): a Coupon applies only to the [Offers](/business/nouns/offer) it names; an Offer may accept several Coupons. `discounts`, inverse [`coupons`](/business/nouns/offer#rel-coupons). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Coupon.create](/business/nouns/coupon/create) | Creates a Coupon. Inherited from [Noun](/business/nouns/noun). | None. | `Coupon.created` | Two-way: `try`, `send`, `do` | | [Coupon.get](/business/nouns/coupon/get) | Returns one Coupon by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Coupon.list](/business/nouns/coupon/list) | Returns Coupons, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Coupon.update](/business/nouns/coupon/update) | Changes the given properties of a Coupon. Inherited from [Noun](/business/nouns/noun). | None. | `Coupon.updated` | Two-way: `try`, `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Coupon.create` | Yes | Yes | Yes | No | | `Coupon.get` | Yes | Yes | Yes | Yes | | `Coupon.list` | Yes | Yes | Yes | Yes | | `Coupon.update` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Add a coupon to QuietCopy. ``` **API** ```bash curl -X POST https://api.sb/quietcopy.com/coupons \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"duration":"once"}' ``` ```json { "api": "https://api.sb/quietcopy.com", "coupon": { "$id": "https://api.sb/quietcopy.com/coupons/coupon_1", "$type": "Coupon", "duration": "once" }, "action": { "$id": "https://api.sb/quietcopy.com/actions/action_1", "operation": "Coupon.create", "status": "done" }, "links": { "self": "https://api.sb/quietcopy.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const coupon = await $.Coupon.create({ duration: 'once' }) ``` **CLI** ```bash npx startup-builder do Coupon.create --json '{"duration":"once"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Coupon.create({ duration: 'once' })" } } ``` ## Example A design tool offers the code `LAUNCH30`: 30% off for 3 months on its yearly and monthly [Offers](/business/nouns/offer). It can be redeemed 500 times before the end of the month. # Credential URL: /business/nouns/credential · Id: `noun:credential` > A Credential is a standing authority a regulator grants a person or entity to perform certain acts in a jurisdiction. A Credential is a standing authority a regulator grants a person or entity to perform certain acts in a jurisdiction. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `issuer` | `string` | Yes | The regulator or registry that grants it. | | `jurisdiction` | `string` | Yes | Where it applies. | | `standing` | `string` | No | Whether it is in good standing, read fresh on every use. | ## Object ```json { "$id": "https://api.sb/patentpad.com/credentials/credential_1", "$type": "Credential", "issuer": "Example issuer", "jurisdiction": "US-DE", "standing": "Example standing" } ``` ## Relationships - A Credential **has** many [Attestations](/business/nouns/attestation): the Credential the signing [Worker](/business/nouns/worker) held when it signed. `attestations`, inverse [`signedUnder`](/business/nouns/attestation#rel-signed-under). - A Credential **authorizes** many [Reserved Acts](/business/nouns/reserved-act): a Credential lets its holder perform the [Reserved Acts](/business/nouns/reserved-act) the law keeps for it, in its jurisdiction. `authorizes`, inverse [`requires`](/business/nouns/reserved-act#rel-requires). - A Credential **is held by** one [Worker](/business/nouns/worker): a [Worker](/business/nouns/worker) performs a [Reserved Act](/business/nouns/reserved-act) only while it holds the Credential that authorizes it, in good standing. `heldBy`, inverse [`holds`](/business/nouns/worker#rel-holds). - A Credential **is held by supplier** one [Supplier](/business/nouns/supplier): the Credentials a [Supplier](/business/nouns/supplier) holds decide which [Reserved Acts](/business/nouns/reserved-act) it may perform; standing is read fresh on every use. `heldBySupplier`, inverse [`holds`](/business/nouns/supplier#rel-holds). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Credential.verify](/business/nouns/credential/verify) | Verify confirms a Credential with the authority that issued it and records when it expires. | [Supply Manager](/agents/operations/supply-manager) | [`Credential.verified`](/business/events/Credential.verified) | None. | | [Credential.create](/business/nouns/credential/create) | Creates a Credential. Inherited from [Noun](/business/nouns/noun). | None. | `Credential.created` | Two-way: `try`, `send`, `do` | | [Credential.get](/business/nouns/credential/get) | Returns one Credential by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Credential.list](/business/nouns/credential/list) | Returns Credentials, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Credential.update](/business/nouns/credential/update) | Changes the given properties of a Credential. Inherited from [Noun](/business/nouns/noun). | None. | `Credential.updated` | Two-way: `try`, `send`, `do` | | [Credential.delete](/business/nouns/credential/delete) | Deletes a Credential; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Credential.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Credential.create` | Yes | Yes | No | No | | `Credential.get` | Yes | Yes | Yes | Yes | | `Credential.list` | Yes | Yes | Yes | Yes | | `Credential.update` | Yes | Yes | No | No | | `Credential.delete` | Yes | Yes | No | No | | `Credential.verify` | Yes | Yes | No | No | ## Call it **Ask** ```text Verify the latest credential. ``` **API** ```bash curl -X POST https://api.sb/tutorloop.com/credentials/credential_1/verify \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/tutorloop.com", "credential": { "$id": "https://api.sb/tutorloop.com/credentials/credential_1", "$type": "Credential", "issuer": "Example issuer", "jurisdiction": "US-DE" }, "action": { "$id": "https://api.sb/tutorloop.com/actions/action_1", "operation": "Credential.verify", "status": "done" }, "links": { "self": "https://api.sb/tutorloop.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const credential = await $.Credential.verify({ credential: 'credential_1' }) ``` **CLI** ```bash npx startup-builder do Credential.verify --json '{"credential":"credential_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Credential.verify({ credential: 'credential_1' })" } } ``` ## Example A state appraiser license is a Credential. A [Supplier](/business/nouns/supplier) holding it performs appraisals in that state until the license lapses. # verify URL: /business/nouns/credential/verify · Id: `verb:Credential.verify` · Call: `await $.Credential.verify({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Verify confirms a Credential with the authority that issued it and records when it expires. Verify confirms a [Credential](/business/nouns/credential) with the authority that issued it and records when it expires. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `credential` | [Credential](/business/nouns/credential) | Yes | The Credential to check. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `credential` | [Credential](/business/nouns/credential) | Yes | The verified Credential. | ## Effects - Emits [`Credential.verified`](/business/events/Credential.verified). - Performed by the [Supply Manager](/agents/operations/supply-manager). - Schedules a recheck before the expiry date. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The input does not match the schema of the operation. | [`invalid-input`](/code/api/errors/invalid-input) | Read the schema of the operation, then send every required field with the right type. | [Credential.verify](/business/nouns/credential/verify) | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Credential.verify](/business/nouns/credential/verify) | | The record is not in a state that allows this Verb, so the call is refused. | [`refused`](/code/api/errors/refused) | Read the record, run the Verb that moves it to an allowed state, then retry. | [Credential.verify](/business/nouns/credential/verify) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Verify the latest credential. ``` **API** ```bash curl -X POST https://api.sb/tutorloop.com/credentials/credential_1/verify \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/tutorloop.com", "credential": { "$id": "https://api.sb/tutorloop.com/credentials/credential_1", "$type": "Credential", "issuer": "Example issuer", "jurisdiction": "US-DE" }, "action": { "$id": "https://api.sb/tutorloop.com/actions/action_1", "operation": "Credential.verify", "status": "done" }, "links": { "self": "https://api.sb/tutorloop.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const credential = await $.Credential.verify({ credential: 'credential_1' }) ``` **CLI** ```bash npx startup-builder do Credential.verify --json '{"credential":"credential_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Credential.verify({ credential: 'credential_1' })" } } ``` # apply URL: /business/nouns/credit-grant/apply · Id: `verb:CreditGrant.apply` · Call: `await $.CreditGrant.apply({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Apply spends Credit Grants against a finalizing Invoice, promotional first, then by priority and earliest expiry, and settles them through Stripe credit grants. Apply spends [Credit Grants](/business/nouns/credit-grant) against a finalizing [Invoice](/business/nouns/invoice), promotional first, then by priority and earliest expiry, and settles them through Stripe credit grants. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `invoice` | [Invoice](/business/nouns/invoice) | Yes | The Invoice being finalized. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `applied` | `money` | Yes | The total the grants paid toward the Invoice. | | `creditGrants` | list of [Credit Grant](/business/nouns/credit-grant) | Yes | Each grant drawn, with its new remaining balance. | ## Effects - Emits [`CreditGrant.applied`](/business/events/CreditGrant.applied). - Performed by the [Billing Specialist](/agents/finance/billing-specialist). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Pays only metered lines of the Startup’s own Offers; credits are never cash and never transfer. - At zero balance, the Offer’s `atBound` behavior applies: stop, overage through the Meter, or upgrade. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [CreditGrant.apply](/business/nouns/credit-grant/apply) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Apply the latest credit grant with an invoice. ``` **API** ```bash curl -X POST https://api.sb/patentpad.com/credit-grants/apply \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"invoice":"invoice_1"}' ``` ```json { "api": "https://api.sb/patentpad.com", "applied": { "amount": 499, "currency": "USD" }, "creditGrants": [ { "$id": "https://api.sb/patentpad.com/credit-grants/credit_grant_1", "$type": "CreditGrant", "amount": { "amount": 499, "currency": "USD" }, "category": "paid" } ], "action": { "$id": "https://api.sb/patentpad.com/actions/action_1", "operation": "CreditGrant.apply", "status": "done" }, "links": { "self": "https://api.sb/patentpad.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { applied, creditGrants } = await $.CreditGrant.apply({ invoice: 'invoice_1' }) ``` **CLI** ```bash npx startup-builder do CreditGrant.apply --json '{"invoice":"invoice_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.CreditGrant.apply({ invoice: 'invoice_1' })" } } ``` # Credit Grant URL: /business/nouns/credit-grant · Id: `noun:credit-grant` > A Credit Grant is a prepaid or promotional balance a Customer spends on a Startup’s metered Offers, checked before each call. A Credit Grant is a prepaid or promotional balance a [Customer](/business/nouns/customer) spends on a [Startup](/business/nouns/startup)’s metered [Offers](/business/nouns/offer), checked before each call. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `amount` | `money` | Yes | The balance granted. Never randomized. | | `category` | `string` | Yes | `paid` (bought through an Order, deferred revenue until spent) or `promotional` (given; never cash). Never randomized. | | `priority` | `integer` | No | Order of use when several grants apply: a lower number spends first, then the earliest expiry. | | `expiresAt` | `datetime` | No | When any remaining balance lapses. Absent means it never lapses. | | `appliesTo` | [Offer](/business/nouns/offer) | No | The metered Offer the balance pays for. Absent means every metered Offer of the Startup. | | `remaining` | `money` | No | The unspent balance, debited once after each metered call and checked as a Limit before the next. | ## Object ```json { "$id": "https://api.sb/tutorloop.com/credit-grants/credit_grant_1", "$type": "CreditGrant", "amount": { "amount": 60, "currency": "USD" }, "category": "paid", "priority": 1, "expiresAt": "2026-10-22T12:00:00Z", "appliesTo": "offer_1", "remaining": { "amount": 60, "currency": "USD" } } ``` ## Relationships - A Credit Grant **credits** one [Customer](/business/nouns/customer): the [Customer](/business/nouns/customer) whose metered calls spend the balance; credits never move to another Customer. `credits`, inverse [`creditGrants`](/business/nouns/customer#rel-credit-grants). - A Credit Grant **offsets** many [Invoices](/business/nouns/invoice): the [Invoices](/business/nouns/invoice) the grant paid toward when they finalized. `offsets`, inverse [`creditGrants`](/business/nouns/invoice#rel-credit-grants). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [CreditGrant.apply](/business/nouns/credit-grant/apply) | Apply spends Credit Grants against a finalizing Invoice, promotional first, then by priority and earliest expiry, and settles them through Stripe credit grants. | [Billing Specialist](/agents/finance/billing-specialist) | [`CreditGrant.applied`](/business/events/CreditGrant.applied) | Two-way: `try`, `send`, `do` | | [CreditGrant.issue](/business/nouns/credit-grant/issue) | Issue gives a Customer a paid or promotional Credit Grant that its metered calls draw down before anything is invoiced. | [Billing Specialist](/agents/finance/billing-specialist) | [`CreditGrant.issued`](/business/events/CreditGrant.issued) | Two-way: `try`, `send`, `do` | | [CreditGrant.void](/business/nouns/credit-grant/void) | Void ends a promotional Credit Grant early and forfeits its remaining balance, keeping the record. | [Billing Specialist](/agents/finance/billing-specialist) | [`CreditGrant.voided`](/business/events/CreditGrant.voided) | One-way (customer): `send`, `do` | | [CreditGrant.create](/business/nouns/credit-grant/create) | Creates a Credit Grant. Inherited from [Noun](/business/nouns/noun). | None. | `CreditGrant.created` | Two-way: `try`, `send`, `do` | | [CreditGrant.get](/business/nouns/credit-grant/get) | Returns one Credit Grant by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [CreditGrant.list](/business/nouns/credit-grant/list) | Returns Credit Grants, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | A Credit Grant is never deleted: it ends by [CreditGrant.void](/business/nouns/credit-grant/void), and its records stay. ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `CreditGrant.create` | Yes | Yes | Yes | No | | `CreditGrant.get` | Yes | Yes | Yes | Yes | | `CreditGrant.list` | Yes | Yes | Yes | Yes | | `CreditGrant.apply` | Yes | Yes | Yes | No | | `CreditGrant.issue` | Yes | Yes | Yes | No | | `CreditGrant.void` | Yes | No | No | No | ## Call it **Ask** ```text Apply the latest credit grant with an invoice. ``` **API** ```bash curl -X POST https://api.sb/patentpad.com/credit-grants/apply \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"invoice":"invoice_1"}' ``` ```json { "api": "https://api.sb/patentpad.com", "applied": { "amount": 499, "currency": "USD" }, "creditGrants": [ { "$id": "https://api.sb/patentpad.com/credit-grants/credit_grant_1", "$type": "CreditGrant", "amount": { "amount": 499, "currency": "USD" }, "category": "paid" } ], "action": { "$id": "https://api.sb/patentpad.com/actions/action_1", "operation": "CreditGrant.apply", "status": "done" }, "links": { "self": "https://api.sb/patentpad.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { applied, creditGrants } = await $.CreditGrant.apply({ invoice: 'invoice_1' }) ``` **CLI** ```bash npx startup-builder do CreditGrant.apply --json '{"invoice":"invoice_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.CreditGrant.apply({ invoice: 'invoice_1' })" } } ``` ## Example A transcription API sells a $100 `paid` Credit Grant and adds a $20 `promotional` grant with priority 1. Each metered call spends the promotional balance first, then the paid one, and a call stops when both reach zero. # issue URL: /business/nouns/credit-grant/issue · Id: `verb:CreditGrant.issue` · Call: `await $.CreditGrant.issue({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Issue gives a Customer a paid or promotional Credit Grant that its metered calls draw down before anything is invoiced. [Issue](/business/nouns/issue) gives a [Customer](/business/nouns/customer) a paid or promotional [Credit Grant](/business/nouns/credit-grant) that its metered calls draw down before anything is invoiced. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `customer` | [Customer](/business/nouns/customer) | Yes | The Customer who receives it. | | `amount` | `money` | Yes | The balance granted. | | `category` | `string` | Yes | `paid` for a balance the Customer bought; `promotional` for one given, which is never cash. | | `appliesTo` | [Offer](/business/nouns/offer) | No | The metered Offer it pays for; every metered Offer of the Startup when absent. | | `expiresAt` | `datetime` | No | When any remaining balance lapses; never, when absent. | | `priority` | `integer` | No | Order of use among grants; a lower number spends first. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `creditGrant` | [Credit Grant](/business/nouns/credit-grant) | Yes | The new Credit Grant, its remaining balance equal to its amount. | ## Effects - Emits [`CreditGrant.issued`](/business/events/CreditGrant.issued). - Performed by the [Billing Specialist](/agents/finance/billing-specialist). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - `Order.pay` issues a `paid` grant on an Offer with `credit`; a `promotional` grant counts against the issuer’s Limit. - Mirrors the grant to Stripe, which applies it when the Invoice finalizes. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [CreditGrant.issue](/business/nouns/credit-grant/issue) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Issue the latest credit grant with a customer. ``` **API** ```bash curl -X POST https://api.sb/quietcopy.com/credit-grants/issue \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"customer":"customer_1","amount":{"amount":39,"currency":"USD"},"category":"paid"}' ``` ```json { "api": "https://api.sb/quietcopy.com", "creditGrant": { "$id": "https://api.sb/quietcopy.com/credit-grants/credit_grant_1", "$type": "CreditGrant", "amount": { "amount": 39, "currency": "USD" }, "category": "paid" }, "action": { "$id": "https://api.sb/quietcopy.com/actions/action_1", "operation": "CreditGrant.issue", "status": "done" }, "links": { "self": "https://api.sb/quietcopy.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const creditGrant = await $.CreditGrant.issue({ customer: 'customer_1', amount: { amount: 39, currency: 'USD' }, category: 'paid' }) ``` **CLI** ```bash npx startup-builder do CreditGrant.issue --json '{"customer":"customer_1","amount":{"amount":39,"currency":"USD"},"category":"paid"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.CreditGrant.issue({ customer: 'customer_1', amount: { amount: 39, currency: 'USD' }, category: 'paid' })" } } ``` # void URL: /business/nouns/credit-grant/void · Id: `verb:CreditGrant.void` · Call: `await $.CreditGrant.void({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Void ends a promotional Credit Grant early and forfeits its remaining balance, keeping the record. Void ends a promotional [Credit Grant](/business/nouns/credit-grant) early and forfeits its remaining balance, keeping the record. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `creditGrant` | [Credit Grant](/business/nouns/credit-grant) | Yes | The grant to end. | | `reason` | `text` | Yes | Why it ends, shown to the Customer. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `creditGrant` | [Credit Grant](/business/nouns/credit-grant) | Yes | The voided grant, its remaining balance zero. | ## Effects - Emits [`CreditGrant.voided`](/business/events/CreditGrant.voided). - Performed by the [Billing Specialist](/agents/finance/billing-specialist). - One-way (customer): it waits out its delay window, and runs in the `send` and `do` modes. - Tells the Customer the balance forfeited and why. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [CreditGrant.void](/business/nouns/credit-grant/void) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Medium: one-way, bounded (customer) | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | 1 business hour, in which a watcher can pause, redirect or cancel it; then it runs. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Void the latest credit grant. ``` **API** ```bash curl -X POST https://api.sb/shiftnote.app/credit-grants/credit_grant_1/void \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"reason":"Example reason"}' ``` ```json { "api": "https://api.sb/shiftnote.app", "creditGrant": { "$id": "https://api.sb/shiftnote.app/credit-grants/credit_grant_1", "$type": "CreditGrant", "amount": { "amount": 79, "currency": "USD" }, "category": "paid" }, "action": { "$id": "https://api.sb/shiftnote.app/actions/action_1", "operation": "CreditGrant.void", "status": "done" }, "links": { "self": "https://api.sb/shiftnote.app/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const creditGrant = await $.CreditGrant.void({ creditGrant: 'credit_grant_1', reason: 'Example reason' }) ``` **CLI** ```bash npx startup-builder do CreditGrant.void --json '{"creditGrant":"credit_grant_1","reason":"Example reason"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.CreditGrant.void({ creditGrant: 'credit_grant_1', reason: 'Example reason' })" } } ``` # Criterion URL: /business/nouns/criterion · Id: `noun:criterion` > A Criterion is one requirement of an outside framework, such as SOC 2 or GDPR, that one or more Controls satisfy. A Criterion is one requirement of an outside framework, such as SOC 2 or GDPR, that one or more [Controls](/business/nouns/control) satisfy. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `framework` | `string` | Yes | One of `soc2`, `iso27001`, `hipaa`, or `gdpr`. | | `ref` | `string` | Yes | The framework’s own reference, such as `CC8.1`. | | `text` | `text` | Yes | The requirement, paraphrased. | ## Object ```json { "$id": "https://api.sb/patentpad.com/criteria/criterion_1", "$type": "Criterion", "framework": "soc2", "ref": "Example ref", "text": "Example text" } ``` ## Relationships None. ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Criterion.get](/business/nouns/criterion/get) | Returns one Criterion by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Criterion.list](/business/nouns/criterion/list) | Returns Criteria, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | A Criterion is kept forever and never edited: it has no `update` or `delete`. ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Criterion.get` | Yes | Yes | Yes | Yes | | `Criterion.list` | Yes | Yes | Yes | Yes | ## Call it **Ask** ```text Show me the latest criterion. ``` **API** ```bash curl https://api.sb/shiftnote.app/criteria/criterion_1 \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/shiftnote.app", "$type": "Criterion", "$id": "https://api.sb/shiftnote.app/criteria/criterion_1", "criterion": { "$id": "https://api.sb/shiftnote.app/criteria/criterion_1", "$type": "Criterion", "framework": "soc2", "ref": "Example ref", "text": "Example text" }, "links": { "self": "https://api.sb/shiftnote.app/criteria/criterion_1", "up": "https://api.sb/shiftnote.app/criteria" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const criterion = await $.Criterion.get({ id: 'criterion_1' }) ``` **CLI** ```bash npx startup-builder do Criterion.get --json '{"id":"criterion_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Criterion.get({ id: 'criterion_1' })" } } ``` ## Example SOC 2 CC8.1 asks that changes be authorized, tested and approved before they reach production. [Change approval](/systems/trust-and-governance/controls/change-approval) satisfies it, and the same Control satisfies ISO 27001 A.8.32. # activate URL: /business/nouns/customer/activate · Id: `verb:Customer.activate` · Call: `await $.Customer.activate({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Activate marks a Customer activated on an Offer once its declared activation Event reaches the count within the window. Activate marks a [Customer](/business/nouns/customer) activated on an [Offer](/business/nouns/offer) once its declared activation [Event](/business/nouns/event) reaches the count within the window. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `customer` | [Customer](/business/nouns/customer) | Yes | The Customer who crossed the line. | | `offer` | [Offer](/business/nouns/offer) | Yes | The Offer whose `activation` was met. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `customer` | [Customer](/business/nouns/customer) | Yes | The activated Customer. | ## Effects - Emits [`Customer.activated`](/business/events/Customer.activated). - Performed by the [Analyst](/agents/marketing/analyst). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Runs once per Customer per Offer, from Product analytics, never by hand. - Activation rate, the onboarding checklist and the silence Watch read the Event. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Customer.activate](/business/nouns/customer/activate) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Activate the latest customer with an offer. ``` **API** ```bash curl -X POST https://api.sb/patentpad.com/customers/customer_1/activate \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"offer":"offer_1"}' ``` ```json { "api": "https://api.sb/patentpad.com", "customer": { "$id": "https://api.sb/patentpad.com/customers/customer_1", "$type": "Customer", "since": "2026-10-22T12:00:00Z" }, "action": { "$id": "https://api.sb/patentpad.com/actions/action_1", "operation": "Customer.activate", "status": "done" }, "links": { "self": "https://api.sb/patentpad.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const customer = await $.Customer.activate({ customer: 'customer_1', offer: 'offer_1' }) ``` **CLI** ```bash npx startup-builder do Customer.activate --json '{"customer":"customer_1","offer":"offer_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Customer.activate({ customer: 'customer_1', offer: 'offer_1' })" } } ``` # exempt URL: /business/nouns/customer/exempt · Id: `verb:Customer.exempt` · Call: `await $.Customer.exempt({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Exempt records a Customer’s exemption or resale certificate, verifies it, and stops tax on its Orders where the certificate applies. Exempt records a [Customer](/business/nouns/customer)’s exemption or resale certificate, verifies it, and stops tax on its [Orders](/business/nouns/order) where the certificate applies. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `customer` | [Customer](/business/nouns/customer) | Yes | The buying Customer. | | `certificate` | [File](/business/nouns/file) | Yes | The certificate as uploaded through the Portal or received by email. | | `jurisdictions` | `string[]` | Yes | Where the certificate applies, such as `US-TX`. | | `expiresOn` | `date` | No | When the certificate lapses; empty when it does not. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `credential` | [Credential](/business/nouns/credential) | Yes | The certificate, held by the Customer’s Organization. | | `customer` | [Customer](/business/nouns/customer) | Yes | The Customer, now exempt where the certificate applies. | ## Effects - Emits [`Customer.exempted`](/business/events/Customer.exempted). - Performed by the [Finance Lead](/agents/finance/finance-lead). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Verifies the certificate number with the issuing authority where it offers a lookup. - Every exempt Order carries the Credential in `taxExemption`. - Asks the Customer for a new certificate 30 days before it lapses. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Customer.exempt](/business/nouns/customer/exempt) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Exempt the latest customer with a file. ``` **API** ```bash curl -X POST https://api.sb/ledgerlark.com/customers/customer_1/exempt \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"certificate":"file_1","jurisdictions":["US-TX"]}' ``` ```json { "api": "https://api.sb/ledgerlark.com", "credential": { "$id": "https://api.sb/ledgerlark.com/credentials/credential_1", "$type": "Credential", "issuer": "Example issuer", "jurisdiction": "US-DE" }, "customer": { "$id": "https://api.sb/ledgerlark.com/customers/customer_1", "$type": "Customer", "since": "2026-10-22T12:00:00Z" }, "action": { "$id": "https://api.sb/ledgerlark.com/actions/action_1", "operation": "Customer.exempt", "status": "done" }, "links": { "self": "https://api.sb/ledgerlark.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { credential, customer } = await $.Customer.exempt({ customer: 'customer_1', certificate: 'file_1', jurisdictions: ['US-TX'] }) ``` **CLI** ```bash npx startup-builder do Customer.exempt --json '{"customer":"customer_1","certificate":"file_1","jurisdictions":["US-TX"]}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Customer.exempt({ customer: 'customer_1', certificate: 'file_1', jurisdictions: ['US-TX'] })" } } ``` # Customer URL: /business/nouns/customer · Id: `noun:customer` > A Customer is a party that has accepted an Offer from a Startup at any price, including zero. A Customer is a party that has accepted an [Offer](/business/nouns/offer) from a [Startup](/business/nouns/startup) at any price, including zero. Interest alone makes a [Lead](/business/nouns/lead), not a Customer. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `since` | `datetime` | Yes | When the party first accepted an Offer. | | `outside` | `boolean` | No | Computed: true when it shares no owner, account, or sibling chain with the Startup. | | `status` | `string` | No | One of `trialing`, `activated`, `atRisk`, `churned`, or `wonBack`, computed from Events and never set by hand; `atRisk` reads customer health. | | `billingEmail` | `email` | No | Where Invoices and receipts go, when it differs from the sign-in email. | | `billingAddress` | `text` | No | The address printed on new Invoices; Stripe Tax reads it to compute tax. | | `taxIds` | `string[]` | No | The Customer’s tax ids, such as a VAT number, printed on new Invoices and read by Stripe Tax. | | `creditRecharge` | `json` | No | When unspent credit falls below `below`, buy `amount` of the credit Offer with the default Payment Source. | ## Object ```json { "$id": "https://api.sb/kilnbakery.com/customers/customer_1", "$type": "Customer", "since": "2026-10-22T12:00:00Z", "outside": true, "status": "trialing", "billingEmail": "tomas@kilnbakery.com", "billingAddress": "Example billing address", "taxIds": [ "Example tax ids" ], "creditRecharge": {} } ``` ## Relationships - A Customer **accepts** many [Offers](/business/nouns/offer): a party becomes a Customer by accepting any [Offer](/business/nouns/offer), at any price including zero. `accepts`, inverse [`acceptedBy`](/business/nouns/offer#rel-accepted-by). - A Customer **is acquired by** one [Acquisition](/business/nouns/acquisition): a Customer inherits the [Acquisition](/business/nouns/acquisition) of the [Lead](/business/nouns/lead) it was; [Metrics](/business/nouns/metric) and payouts read this one row. `acquiredBy`, inverse [`customers`](/business/nouns/acquisition#rel-customers). - A Customer **has** one [Contact](/business/nouns/contact): a [Contact](/business/nouns/contact) becomes a Customer on accepting an [Offer](/business/nouns/offer). `contact`, inverse [`becomes`](/business/nouns/contact#rel-becomes). - A Customer **has** many [Credit Grants](/business/nouns/credit-grant): the Customer whose metered calls spend the balance; credits never move to another Customer. `creditGrants`, inverse [`credits`](/business/nouns/credit-grant#rel-credits). - A Customer **holds** many [Entitlements](/business/nouns/entitlement): a Customer’s [Entitlements](/business/nouns/entitlement) are what it may do right now, granted by the [Offers](/business/nouns/offer) it accepted. `holds`, inverse [`heldBy`](/business/nouns/entitlement#rel-held-by). - A Customer **has** many [Invoices](/business/nouns/invoice): each [Invoice](/business/nouns/invoice) is owed by one Customer. `invoices`, inverse [`charges`](/business/nouns/invoice#rel-charges). - A Customer **maintains** many [Subscriptions](/business/nouns/subscription): a Customer holds [Subscriptions](/business/nouns/subscription), each billed once per [Period](/business/nouns/period). `maintains`, inverse [`subscriber`](/business/nouns/subscription#rel-subscriber). - A Customer **opens** many [Conversations](/business/nouns/conversation): the Customer a [Conversation](/business/nouns/conversation) serves, so every answer reads that Customer’s records. `opens`, inverse [`customer`](/business/nouns/conversation#rel-customer). - A Customer **owns** one [Tenant](/business/nouns/tenant): each Customer has one [Tenant](/business/nouns/tenant): the partition of the [Startup](/business/nouns/startup)’s data that no other Customer reads. `owns`, inverse [`ownedBy`](/business/nouns/tenant#rel-owned-by). - A Customer **places** many [Orders](/business/nouns/order): a Customer commits to one-time purchases as [Orders](/business/nouns/order). `places`, inverse [`placedBy`](/business/nouns/order#rel-placed-by). - A Customer **saves** many [Payment Sources](/business/nouns/payment-source): a Customer saves the [Payment Sources](/business/nouns/payment-source) its [Orders](/business/nouns/order), [Subscriptions](/business/nouns/subscription) and [Invoices](/business/nouns/invoice) charge; each belongs to one [Startup](/business/nouns/startup) and never moves to a sibling. `saves`, inverse [`savedBy`](/business/nouns/payment-source#rel-saved-by). - A Customer **is served by** one [Startup](/business/nouns/startup): a [Startup](/business/nouns/startup) serves every party that has accepted one of its [Offers](/business/nouns/offer). `servedBy`, inverse [`serves`](/business/nouns/startup#rel-serves). - A Customer **signs into** one [Portal](/business/nouns/portal): Customers sign in to a [Portal](/business/nouns/portal) to order, track delivery, accept work, and pay. `signsInto`, inverse [`serves`](/business/nouns/portal#rel-serves). ## Lifecycle | State | Meaning | Moves to | | --- | --- | --- | | `trialing` (first) | It accepted an Offer and has not yet reached the Offer’s activation Event. | `activated` on [`Customer.activated`](/business/events/Customer.activated); `churned` on [`Subscription.unsubscribed`](/business/events/Subscription.unsubscribed) when it ends its last active Subscription | | `activated` | It reached its Offer’s activation Event within the window and pays on time. | `atRisk` on [`Subscription.pastDue`](/business/nouns/subscription#subscriptionpastdue) when the Subscription is this Customer’s; `atRisk` on [`Dispute.opened`](/business/nouns/dispute#disputeopened) when the disputed charge is this Customer’s; `churned` on [`Subscription.unsubscribed`](/business/events/Subscription.unsubscribed) when it ends its last active Subscription | | `atRisk` | A renewal is past due, a Dispute is open, or its health reading fell below the line. | `activated` on [`Invoice.collected`](/business/events/Invoice.collected) when the overdue Invoice is this Customer’s; `churned` on [`Subscription.unsubscribed`](/business/events/Subscription.unsubscribed) when it ends its last active Subscription | | `churned` | It holds no active Subscription and placed no Order in the window; its record stays. | `wonBack` on [`Offer.subscribed`](/business/events/Offer.subscribed) when the subscriber is this Customer; `wonBack` on [`Order.placed`](/business/events/Order.placed) when the buyer is this Customer | | `wonBack` | A churned Customer that subscribed or bought again. | `atRisk` on [`Subscription.pastDue`](/business/nouns/subscription#subscriptionpastdue) when the Subscription is this Customer’s; `churned` on [`Subscription.unsubscribed`](/business/events/Subscription.unsubscribed) when it ends its last active Subscription | ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Offer.accept](/business/nouns/offer/accept) | Accept records that a party takes an Offer, which makes that party a Customer of the Startup. | [Customer](/business/nouns/customer) | [`Offer.accepted`](/business/events/Offer.accepted) | None. | | [Quote.accept](/business/nouns/quote/accept) | Accept takes a sent Quote before it expires, turning one-time lines into an Order and recurring lines into a Subscription. | [Sales Engineer](/agents/sales/sales-engineer) | [`Quote.accepted`](/business/events/Quote.accepted) | One-way: `send`, `do` | | [Customer.activate](/business/nouns/customer/activate) | Activate marks a Customer activated on an Offer once its declared activation Event reaches the count within the window. | [Analyst](/agents/marketing/analyst) | [`Customer.activated`](/business/events/Customer.activated) | Two-way: `try`, `send`, `do` | | [PaymentSource.add](/business/nouns/payment-source/add) | Add saves a new Payment Source for a Customer through Stripe’s embedded form on the Startup’s Domain, and can make it the default. | [Billing Specialist](/agents/finance/billing-specialist) | [`PaymentSource.added`](/business/events/PaymentSource.added) | Two-way: `try`, `send`, `do` | | [Order.cancel](/business/nouns/order/cancel) | Cancel ends an Order before fulfillment and returns any payment in full. | [Customer](/business/nouns/customer) | [`Order.canceled`](/business/events/Order.canceled) | Two-way: `try`, `send`, `do` | | [Order.confirm](/business/nouns/order/confirm) | Confirm records the Customer’s sign-off on delivered work, which closes the Order and earns the Startup its fee. | [Delivery Manager](/agents/operations/delivery-manager) | [`Order.confirmed`](/business/events/Order.confirmed) | One-way (money): `send`, `do` | | [Order.dispute](/business/nouns/order/dispute) | Dispute contests a delivered Order under its Outcome Contract and starts the remedy the contract names. | [Billing Specialist](/agents/finance/billing-specialist) | [`Order.disputed`](/business/events/Order.disputed) | Two-way: `try`, `send`, `do` | | [Customer.exempt](/business/nouns/customer/exempt) | Exempt records a Customer’s exemption or resale certificate, verifies it, and stops tax on its Orders where the certificate applies. | [Finance Lead](/agents/finance/finance-lead) | [`Customer.exempted`](/business/events/Customer.exempted) | Two-way: `try`, `send`, `do` | | [Tenant.invite](/business/nouns/tenant/invite) | Invite asks a Person to join a Customer’s Tenant, and resizes the Subscription when the Offer prices per member. | [Security Engineer](/agents/engineering/security-engineer) | [`Tenant.invited`](/business/events/Tenant.invited) | Two-way: `try`, `send`, `do` | | [Subscription.keep](/business/nouns/subscription/keep) | Keep takes back a cancel before the period closes, so the Subscription renews on its date at the same terms. | [Billing Specialist](/agents/finance/billing-specialist) | [`Subscription.kept`](/business/events/Subscription.kept) | Two-way: `try`, `send`, `do` | | [Subscription.pause](/business/nouns/subscription/pause) | Pause stops billing and Entitlements on a Subscription until a date, without ending it. | [Billing Specialist](/agents/finance/billing-specialist) | [`Subscription.paused`](/business/events/Subscription.paused) | Two-way: `try`, `send`, `do` | | [Order.pay](/business/nouns/order/pay) | Pay settles an Order’s amount through the Startup’s payment account and posts the matching Entries. | [Billing Specialist](/agents/finance/billing-specialist) | [`Order.paid`](/business/events/Order.paid) | One-way (money): `send`, `do` | | [Tenant.pin](/business/nouns/tenant/pin) | Pin moves a Tenant’s keys to another API version, or to `latest`, once a call with its test key passes there. | [Customer](/business/nouns/customer) | [`Tenant.pinned`](/business/events/Tenant.pinned) | Two-way: `try`, `send`, `do` | | [Order.place](/business/nouns/order/place) | Place commits a Customer to buy an Offer once and records the Offer Version and price at that moment. | [Founder](/agents/founding/founder) | [`Order.placed`](/business/events/Order.placed) | Two-way: `try`, `send`, `do` | | [PaymentSource.remove](/business/nouns/payment-source/remove) | Remove detaches a saved Payment Source so nothing charges it again, and keeps the record. | [Billing Specialist](/agents/finance/billing-specialist) | [`PaymentSource.removed`](/business/events/PaymentSource.removed) | Two-way: `try`, `send`, `do` | | [Subscription.resize](/business/nouns/subscription/resize) | Resize changes how many units a Subscription holds and prorates the current period. | [Billing Specialist](/agents/finance/billing-specialist) | [`Subscription.resized`](/business/events/Subscription.resized) | Two-way: `try`, `send`, `do` | | [Subscription.resume](/business/nouns/subscription/resume) | Resume restarts billing and Entitlements on a paused Subscription before its pause ends. | [Billing Specialist](/agents/finance/billing-specialist) | [`Subscription.resumed`](/business/events/Subscription.resumed) | Two-way: `try`, `send`, `do` | | [Order.revise](/business/nouns/order/revise) | Revise sends delivered lines back for one counted revision, with the changes the Customer asks for. | [Delivery Manager](/agents/operations/delivery-manager) | [`Order.revised`](/business/events/Order.revised) | Two-way: `try`, `send`, `do` | | [Offer.subscribe](/business/nouns/offer/subscribe) | Subscribe accepts a recurring Offer as a Subscription that renews each period until it ends. | [Billing Specialist](/agents/finance/billing-specialist) | [`Offer.subscribed`](/business/events/Offer.subscribed) | None. | | [Subscription.switch](/business/nouns/subscription/switch) | Switch moves a Subscription to another Offer and prorates the current period. | [Billing Specialist](/agents/finance/billing-specialist) | [`Subscription.switched`](/business/events/Subscription.switched) | Two-way: `try`, `send`, `do` | | [Offer.trial](/business/nouns/offer/trial) | Trial starts a Customer on an Offer free for a set number of days, with or without a card, converting or ending by its terms. | [Billing Specialist](/agents/finance/billing-specialist) | [`Offer.trialed`](/business/events/Offer.trialed) | Two-way: `try`, `send`, `do` | | [Subscription.unsubscribe](/business/nouns/subscription/unsubscribe) | Unsubscribe ends a Subscription at the close of its current period, and the Customer keeps access until then. | [Billing Specialist](/agents/finance/billing-specialist) | [`Subscription.unsubscribed`](/business/events/Subscription.unsubscribed) | Two-way: `try`, `send`, `do` | | [Customer.create](/business/nouns/customer/create) | Creates a Customer. Inherited from [Noun](/business/nouns/noun). | None. | `Customer.created` | Two-way: `try`, `send`, `do` | | [Customer.get](/business/nouns/customer/get) | Returns one Customer by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Customer.list](/business/nouns/customer/list) | Returns Customers, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Customer.update](/business/nouns/customer/update) | Changes the given properties of a Customer. Inherited from [Noun](/business/nouns/noun). | None. | `Customer.updated` | Two-way: `try`, `send`, `do` | | [Customer.delete](/business/nouns/customer/delete) | Deletes a Customer; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Customer.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Customer.create` | Yes | Yes | Yes | No | | `Customer.get` | Yes | Yes | Yes | Yes | | `Customer.list` | Yes | Yes | Yes | Yes | | `Customer.update` | Yes | Yes | Yes | No | | `Customer.delete` | Yes | Yes | Yes | No | | `Customer.activate` | Yes | Yes | Yes | No | | `Customer.exempt` | Yes | Yes | Yes | No | ## Stripe **Customer** (`customer`). The source of truth is db.sb, and Stripe holds a copy written from it. | Property | Stripe field | Source of truth | | --- | --- | --- | | `billingEmail` | `email` | db.sb | | `billingAddress` | `address` | db.sb | | `taxIds` | `tax_ids.data[].value` | db.sb | ## Call it **Ask** ```text Activate the latest customer with an offer. ``` **API** ```bash curl -X POST https://api.sb/patentpad.com/customers/customer_1/activate \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"offer":"offer_1"}' ``` ```json { "api": "https://api.sb/patentpad.com", "customer": { "$id": "https://api.sb/patentpad.com/customers/customer_1", "$type": "Customer", "since": "2026-10-22T12:00:00Z" }, "action": { "$id": "https://api.sb/patentpad.com/actions/action_1", "operation": "Customer.activate", "status": "done" }, "links": { "self": "https://api.sb/patentpad.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const customer = await $.Customer.activate({ customer: 'customer_1', offer: 'offer_1' }) ``` **CLI** ```bash npx startup-builder do Customer.activate --json '{"customer":"customer_1","offer":"offer_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Customer.activate({ customer: 'customer_1', offer: 'offer_1' })" } } ``` ## Example A developer who takes a $0 API key accepts an Offer and becomes a Customer, with `since` set to that day. A developer who joins the [Waitlist](/business/nouns/waitlist) accepts nothing and stays a Lead. # ask URL: /business/nouns/dashboard/ask · Id: `verb:Dashboard.ask` · Call: `await $.Dashboard.ask({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Ask answers a plain-language question with a query over the Startup’s records and shows the query beside the result. Ask answers a plain-language question with a query over the [Startup](/business/nouns/startup)’s records and shows the query beside the result. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `question` | `text` | Yes | The question, in plain language. | | `dashboard` | [Dashboard](/business/nouns/dashboard) | No | The Dashboard to add the answer to as a tile. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `query` | `text` | Yes | The query it ran, to read and reuse. | | `rows` | `json` | Yes | The result, as a table or chart. | | `dashboard` | [Dashboard](/business/nouns/dashboard) | Yes | The Dashboard the question was asked on. | ## Effects - Emits [`Dashboard.asked`](/business/events/Dashboard.asked). - Performed by the [Analyst](/agents/marketing/analyst). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Reads only records the asker’s Permissions allow. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Dashboard.ask](/business/nouns/dashboard/ask) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Ask my dashboard. ``` **API** ```bash curl -X POST https://api.sb/patentpad.com/dashboards/ask \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"question":"Example question"}' ``` ```json { "api": "https://api.sb/patentpad.com", "query": "Example query", "rows": {}, "dashboard": { "$id": "https://api.sb/patentpad.com/dashboards/dashboard_1", "$type": "Dashboard", "scope": "Startup" }, "action": { "$id": "https://api.sb/patentpad.com/actions/action_1", "operation": "Dashboard.ask", "status": "done" }, "links": { "self": "https://api.sb/patentpad.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { query, rows, dashboard } = await $.Dashboard.ask({ question: 'Example question' }) ``` **CLI** ```bash npx startup-builder do Dashboard.ask --json '{"question":"Example question"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Dashboard.ask({ question: 'Example question' })" } } ``` Next: [`Dashboard.schedule`](/business/nouns/dashboard/schedule) (in `guide:how-is-it-going`). Guides that call it: [How is it going](/start/guides/how-is-it-going). # Dashboard URL: /business/nouns/dashboard · Id: `noun:dashboard` > A Dashboard is one unified view of a scope, rendered as Markdown for Agents, screens for Humans, and JSON for native clients. A Dashboard is one unified view of a scope, rendered as Markdown for [Agents](/business/nouns/agent), screens for [Humans](/business/nouns/human), and JSON for native clients. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `scope` | `string` | Yes | What it views, such as a Studio, a Startup, a Team, or a Role. | ## Object ```json { "$id": "https://api.sb/tutorloop.com/dashboards/dashboard_1", "$type": "Dashboard", "scope": "Startup" } ``` ## Relationships - A Dashboard **is presented in** one [App](/business/nouns/app): an [App](/business/nouns/app) opens on Dashboards for the people signed in to it. `presentedIn`, inverse [`presents`](/business/nouns/app#rel-presents). - A Dashboard **shows** many [Metrics](/business/nouns/metric): a Dashboard reads out [Metrics](/business/nouns/metric), each computed from [Events](/business/nouns/event) and never typed in. `shows`, inverse [`shownOn`](/business/nouns/metric#rel-shown-on). - A Dashboard **views** one [Thing](/business/nouns/thing): a Dashboard summarizes one scope, such as a [Studio](/business/nouns/studio), a [Startup](/business/nouns/startup), a [Team](/business/nouns/team), or a [Role](/business/nouns/role). `views`, inverse [`dashboards`](/business/nouns/thing#rel-dashboards). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Dashboard.ask](/business/nouns/dashboard/ask) | Ask answers a plain-language question with a query over the Startup’s records and shows the query beside the result. | [Analyst](/agents/marketing/analyst) | [`Dashboard.asked`](/business/events/Dashboard.asked) | Two-way: `try`, `send`, `do` | | [Dashboard.schedule](/business/nouns/dashboard/schedule) | Schedule sends a Dashboard on a cadence to a Mailbox, a Channel or an Agent’s context, rendered for each. | [Analyst](/agents/marketing/analyst) | [`Dashboard.scheduled`](/business/events/Dashboard.scheduled) | Two-way: `try`, `send`, `do` | | [Dashboard.create](/business/nouns/dashboard/create) | Creates a Dashboard. Inherited from [Noun](/business/nouns/noun). | None. | `Dashboard.created` | Two-way: `try`, `send`, `do` | | [Dashboard.get](/business/nouns/dashboard/get) | Returns one Dashboard by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Dashboard.list](/business/nouns/dashboard/list) | Returns Dashboards, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Dashboard.update](/business/nouns/dashboard/update) | Changes the given properties of a Dashboard. Inherited from [Noun](/business/nouns/noun). | None. | `Dashboard.updated` | Two-way: `try`, `send`, `do` | | [Dashboard.delete](/business/nouns/dashboard/delete) | Deletes a Dashboard; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Dashboard.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Dashboard.create` | Yes | Yes | Yes | No | | `Dashboard.get` | Yes | Yes | Yes | Yes | | `Dashboard.list` | Yes | Yes | Yes | Yes | | `Dashboard.update` | Yes | Yes | Yes | No | | `Dashboard.delete` | Yes | Yes | Yes | No | | `Dashboard.ask` | Yes | Yes | Yes | No | | `Dashboard.schedule` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Ask my dashboard. ``` **API** ```bash curl -X POST https://api.sb/patentpad.com/dashboards/ask \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"question":"Example question"}' ``` ```json { "api": "https://api.sb/patentpad.com", "query": "Example query", "rows": {}, "dashboard": { "$id": "https://api.sb/patentpad.com/dashboards/dashboard_1", "$type": "Dashboard", "scope": "Startup" }, "action": { "$id": "https://api.sb/patentpad.com/actions/action_1", "operation": "Dashboard.ask", "status": "done" }, "links": { "self": "https://api.sb/patentpad.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { query, rows, dashboard } = await $.Dashboard.ask({ question: 'Example question' }) ``` **CLI** ```bash npx startup-builder do Dashboard.ask --json '{"question":"Example question"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Dashboard.ask({ question: 'Example question' })" } } ``` ## Example The [Founder](/agents/founding/founder) Dashboard of a tutoring marketplace shows bookings, open tutor hours, and runway. An [Agent](/business/nouns/agent) reads it as Markdown in its context, and the founder reads the same view on a phone. # schedule URL: /business/nouns/dashboard/schedule · Id: `verb:Dashboard.schedule` · Call: `await $.Dashboard.schedule({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Schedule sends a Dashboard on a cadence to a Mailbox, a Channel or an Agent’s context, rendered for each. Schedule sends a [Dashboard](/business/nouns/dashboard) on a cadence to a [Mailbox](/business/nouns/mailbox), a [Channel](/business/nouns/channel) or an [Agent](/business/nouns/agent)’s context, rendered for each. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `dashboard` | [Dashboard](/business/nouns/dashboard) | Yes | The Dashboard to send. | | `cadence` | `string` | Yes | How often it goes out. | | `to` | `string` | Yes | The Mailbox, Channel or Agent that receives it. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `dashboard` | [Dashboard](/business/nouns/dashboard) | Yes | The Dashboard, with its schedule. | ## Effects - Emits [`Dashboard.scheduled`](/business/events/Dashboard.scheduled). - Performed by the [Analyst](/agents/marketing/analyst). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Agents receive Markdown; Humans receive the rendered view. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Dashboard.schedule](/business/nouns/dashboard/schedule) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Schedule my dashboard. ``` **API** ```bash curl -X POST https://api.sb/shiftnote.app/dashboards/dashboard_1/schedule \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"cadence":"daily","to":"Example to"}' ``` ```json { "api": "https://api.sb/shiftnote.app", "dashboard": { "$id": "https://api.sb/shiftnote.app/dashboards/dashboard_1", "$type": "Dashboard", "scope": "Startup" }, "action": { "$id": "https://api.sb/shiftnote.app/actions/action_1", "operation": "Dashboard.schedule", "status": "done" }, "links": { "self": "https://api.sb/shiftnote.app/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const dashboard = await $.Dashboard.schedule({ dashboard: 'dashboard_1', cadence: 'daily', to: 'Example to' }) ``` **CLI** ```bash npx startup-builder do Dashboard.schedule --json '{"dashboard":"dashboard_1","cadence":"daily","to":"Example to"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Dashboard.schedule({ dashboard: 'dashboard_1', cadence: 'daily', to: 'Example to' })" } } ``` Guides that call it: [How is it going](/start/guides/how-is-it-going). # Dataset URL: /business/nouns/dataset · Id: `noun:dataset` > A Dataset is a Product of curated Things of one Noun, with a promise that they are true. A Dataset is a [Product](/business/nouns/product) of curated [Things](/business/nouns/thing) of one [Noun](/business/nouns/noun), with a promise that they are true. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `records` | `integer` | No | How many Things it holds. | | `refreshedAt` | `datetime` | No | When its Sources were last read. |
Inherited from [Product](/business/nouns/product): 3 properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `name` | `string` | Yes | The name of the Product. | | `promise` | `text` | Yes | What the Customer can rely on. | | `status` | `string` | Yes | One of `draft`, `selling` or `retired`, set by its Offers. |
## Object ```json { "$id": "https://api.sb/tutorloop.com/datasets/dataset_1", "$type": "Dataset", "name": "TutorLoop", "promise": "A tutor confirmed within one hour.", "status": "draft", "records": 1, "refreshedAt": "2026-10-22T12:00:00Z" } ``` ## Relationships - A Dataset **curates** one [Noun](/business/nouns/noun): a Dataset collects and vouches for the [Things](/business/nouns/thing) of exactly one [Noun](/business/nouns/noun). `curates`, inverse [`curatedIn`](/business/nouns/noun#rel-curated-in). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Dataset.create](/business/nouns/dataset/create) | Creates a Dataset. Inherited from [Noun](/business/nouns/noun). | None. | `Dataset.created` | Two-way: `try`, `send`, `do` | | [Dataset.get](/business/nouns/dataset/get) | Returns one Dataset by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Dataset.list](/business/nouns/dataset/list) | Returns Datasets, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Dataset.update](/business/nouns/dataset/update) | Changes the given properties of a Dataset. Inherited from [Noun](/business/nouns/noun). | None. | `Dataset.updated` | Two-way: `try`, `send`, `do` | | [Dataset.delete](/business/nouns/dataset/delete) | Deletes a Dataset; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Dataset.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Dataset.create` | Yes | Yes | Yes | No | | `Dataset.get` | Yes | Yes | Yes | Yes | | `Dataset.list` | Yes | Yes | Yes | Yes | | `Dataset.update` | Yes | Yes | Yes | No | | `Dataset.delete` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Add a dataset to QuietCopy. ``` **API** ```bash curl -X POST https://api.sb/quietcopy.com/datasets \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"name":"QuietCopy","promise":"Line-by-line edits within one day."}' ``` ```json { "api": "https://api.sb/quietcopy.com", "dataset": { "$id": "https://api.sb/quietcopy.com/datasets/dataset_1", "$type": "Dataset", "name": "QuietCopy", "promise": "Line-by-line edits within one day.", "status": "draft" }, "action": { "$id": "https://api.sb/quietcopy.com/actions/action_1", "operation": "Dataset.create", "status": "done" }, "links": { "self": "https://api.sb/quietcopy.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const dataset = await $.Dataset.create({ name: 'QuietCopy', promise: 'Line-by-line edits within one day.' }) ``` **CLI** ```bash npx startup-builder do Dataset.create --json '{"name":"QuietCopy","promise":"Line-by-line edits within one day."}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Dataset.create({ name: 'QuietCopy', promise: 'Line-by-line edits within one day.' })" } } ``` ## Example A Dataset of 4.2 million business registrations across 50 states refreshes nightly. It promises each record matches the state filing as of its `refreshedAt`. # advance URL: /business/nouns/deal/advance · Id: `verb:Deal.advance` · Call: `await $.Deal.advance({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Advance moves a Deal to its next stage once every field that stage requires is filled. Advance moves a [Deal](/business/nouns/deal) to its next stage once every field that stage requires is filled. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `deal` | [Deal](/business/nouns/deal) | Yes | The Deal. | | `stage` | `string` | No | The target stage; omitted, the next one. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `deal` | [Deal](/business/nouns/deal) | Yes | The Deal in its new stage. | ## Effects - Emits [`Deal.advanced`](/business/events/Deal.advanced). - Performed by the [Sales Lead](/agents/sales/sales-lead). - Two-way: it runs at once, in the `try`, `send` and `do` modes. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Deal.advance](/business/nouns/deal/advance) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Advance the latest deal. ``` **API** ```bash curl -X POST https://api.sb/tutorloop.com/deals/deal_1/advance \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/tutorloop.com", "deal": { "$id": "https://api.sb/tutorloop.com/deals/deal_1", "$type": "Deal", "status": "Open" }, "action": { "$id": "https://api.sb/tutorloop.com/actions/action_1", "operation": "Deal.advance", "status": "done" }, "links": { "self": "https://api.sb/tutorloop.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const deal = await $.Deal.advance({ deal: 'deal_1' }) ``` **CLI** ```bash npx startup-builder do Deal.advance --json '{"deal":"deal_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Deal.advance({ deal: 'deal_1' })" } } ``` # assign URL: /business/nouns/deal/assign · Id: `verb:Deal.assign` · Call: `await $.Deal.assign({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Assign gives a Deal one owner Worker, who carries its next step until it is won or lost. Assign gives a [Deal](/business/nouns/deal) one owner [Worker](/business/nouns/worker), who carries its next step until it is won or lost. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `deal` | [Deal](/business/nouns/deal) | Yes | The Deal. | | `owner` | [Worker](/business/nouns/worker) | No | The Worker to own it; omitted, the routing Policy picks. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `deal` | [Deal](/business/nouns/deal) | Yes | The Deal, with its owner. | ## Effects - Emits [`Deal.assigned`](/business/events/Deal.assigned). - Performed by the [Sales Lead](/agents/sales/sales-lead). - Two-way: it runs at once, in the `try`, `send` and `do` modes. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Deal.assign](/business/nouns/deal/assign) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Assign the latest deal. ``` **API** ```bash curl -X POST https://api.sb/ledgerlark.com/deals/deal_1/assign \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/ledgerlark.com", "deal": { "$id": "https://api.sb/ledgerlark.com/deals/deal_1", "$type": "Deal", "status": "Open" }, "action": { "$id": "https://api.sb/ledgerlark.com/actions/action_1", "operation": "Deal.assign", "status": "done" }, "links": { "self": "https://api.sb/ledgerlark.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const deal = await $.Deal.assign({ deal: 'deal_1' }) ``` **CLI** ```bash npx startup-builder do Deal.assign --json '{"deal":"deal_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Deal.assign({ deal: 'deal_1' })" } } ``` # Deal URL: /business/nouns/deal · Id: `noun:deal` > A Deal is a Startup’s pursuit of one buyer’s acceptance of one or more Offers, ending won or lost. A Deal is a [Startup](/business/nouns/startup)’s pursuit of one buyer’s acceptance of one or more [Offers](/business/nouns/offer), ending won or lost. It is won when the buyer accepts a [Quote](/business/nouns/quote), and lost with the buyer’s reason. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `status` | `string` | Yes | One of `Open`, `Qualified`, `Proposed`, `Won`, or `Lost`. | | `value` | `money` | No | What the Deal is worth if won. | | `owner` | [Worker](/business/nouns/worker) | No | The Worker who runs it. | | `closesOn` | `date` | No | The date the buyer expects to decide. | | `statusSince` | `datetime` | No | When it entered its current status, computed from its Events. | | `nextStep` | `text` | No | The next dated step agreed with the buyer. | ## Object ```json { "$id": "https://api.sb/quietcopy.com/deals/deal_1", "$type": "Deal", "status": "Open", "value": { "amount": 39, "currency": "USD" }, "owner": "worker_1", "closesOn": "2026-10-22", "statusSince": "2026-10-22T12:00:00Z", "nextStep": "Example next step" } ``` ## Relationships - A Deal **courts** one [Organization](/business/nouns/organization): each Deal has one buying [Organization](/business/nouns/organization) on the other side. `courts`, inverse [`deals`](/business/nouns/organization#rel-deals). - A Deal **issues** many [Quotes](/business/nouns/quote): a Deal sends [Quotes](/business/nouns/quote), each a priced proposal valid until a date. `issues`, inverse [`issuedIn`](/business/nouns/quote#rel-issued-in). - A Deal **has** many [Meetings](/business/nouns/meeting): a [Meeting](/business/nouns/meeting) moves one Deal forward. `meetings`, inverse [`advances`](/business/nouns/meeting#rel-advances). - A Deal **pursues** many [Offers](/business/nouns/offer): a Deal asks one buyer to accept one or more [Offers](/business/nouns/offer). `pursues`, inverse [`pursuedIn`](/business/nouns/offer#rel-pursued-in). - A Deal **is sourced by** one [Referral](/business/nouns/referral): the Deals a [Referral](/business/nouns/referral) opened; when one is won, its revenue earns the [Partner](/business/nouns/partner)’s [Commission](/business/nouns/commission). `sourcedBy`, inverse [`sources`](/business/nouns/referral#rel-sources). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Deal.advance](/business/nouns/deal/advance) | Advance moves a Deal to its next stage once every field that stage requires is filled. | [Sales Lead](/agents/sales/sales-lead) | [`Deal.advanced`](/business/events/Deal.advanced) | Two-way: `try`, `send`, `do` | | [Deal.assign](/business/nouns/deal/assign) | Assign gives a Deal one owner Worker, who carries its next step until it is won or lost. | [Sales Lead](/agents/sales/sales-lead) | [`Deal.assigned`](/business/events/Deal.assigned) | Two-way: `try`, `send`, `do` | | [Deal.lose](/business/nouns/deal/lose) | Lose closes a Deal as lost and records the reason the buyer gave. | [Sales Lead](/agents/sales/sales-lead) | [`Deal.lost`](/business/events/Deal.lost) | None. | | [Deal.propose](/business/nouns/deal/propose) | Propose sends a Deal’s buyer a Quote they accept to place an Order. | [Sales Lead](/agents/sales/sales-lead) | [`Deal.proposed`](/business/events/Deal.proposed) | One-way (money, customer): `send`, `do` | | [Deal.win](/business/nouns/deal/win) | Win closes a Deal as won, which places its Order and makes the buyer a Customer. | [Sales Lead](/agents/sales/sales-lead) | [`Deal.won`](/business/events/Deal.won) | None. | | [Deal.create](/business/nouns/deal/create) | Creates a Deal. Inherited from [Noun](/business/nouns/noun). | None. | `Deal.created` | Two-way: `try`, `send`, `do` | | [Deal.get](/business/nouns/deal/get) | Returns one Deal by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Deal.list](/business/nouns/deal/list) | Returns Deals, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Deal.update](/business/nouns/deal/update) | Changes the given properties of a Deal. Inherited from [Noun](/business/nouns/noun). | None. | `Deal.updated` | Two-way: `try`, `send`, `do` | | [Deal.delete](/business/nouns/deal/delete) | Deletes a Deal; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Deal.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Deal.create` | Yes | Yes | Yes | No | | `Deal.get` | Yes | Yes | Yes | Yes | | `Deal.list` | Yes | Yes | Yes | Yes | | `Deal.update` | Yes | Yes | Yes | No | | `Deal.delete` | Yes | Yes | Yes | No | | `Deal.advance` | Yes | Yes | Yes | No | | `Deal.assign` | Yes | Yes | Yes | No | | `Deal.lose` | Yes | Yes | Yes | No | | `Deal.propose` | Yes | No | No | No | | `Deal.win` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Propose the latest deal with a quote. ``` **API** ```bash curl -X POST https://api.sb/quietcopy.com/deals/deal_1/propose \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"quote":"quote_1"}' ``` ```json { "api": "https://api.sb/quietcopy.com", "deal": { "$id": "https://api.sb/quietcopy.com/deals/deal_1", "$type": "Deal", "status": "Proposed" }, "action": { "$id": "https://api.sb/quietcopy.com/actions/action_1", "operation": "Deal.propose", "status": "done" }, "links": { "self": "https://api.sb/quietcopy.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const deal = await $.Deal.propose({ deal: 'deal_1', quote: 'quote_1' }) ``` **CLI** ```bash npx startup-builder do Deal.propose --json '{"deal":"deal_1","quote":"quote_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Deal.propose({ deal: 'deal_1', quote: 'quote_1' })" } } ``` ## Example A Deal with a county planning firm pursues the $900-a-month permit-records Offer plus a $3,000 backfill: `value: 13,800` for year one. After two [Meetings](/business/nouns/meeting) the firm accepts the Quote, and [`Quote.accept`](/business/nouns/quote/accept) wins the Deal. # lose URL: /business/nouns/deal/lose · Id: `verb:Deal.lose` · Call: `await $.Deal.lose({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Lose closes a Deal as lost and records the reason the buyer gave. Lose closes a [Deal](/business/nouns/deal) as lost and records the reason the buyer gave. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `deal` | [Deal](/business/nouns/deal) | Yes | The open Deal. | | `reason` | `text` | Yes | Why the buyer passed. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `deal` | [Deal](/business/nouns/deal) | Yes | The lost Deal. | ## Effects - Emits [`Deal.lost`](/business/events/Deal.lost). - Performed by the [Sales Lead](/agents/sales/sales-lead). ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Deal.lose](/business/nouns/deal/lose) | | The record is not in a state that allows this Verb, so the call is refused. | [`refused`](/code/api/errors/refused) | Read the record, run the Verb that moves it to an allowed state, then retry. | [Deal.lose](/business/nouns/deal/lose) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Lose the latest deal. ``` **API** ```bash curl -X POST https://api.sb/shiftnote.app/deals/deal_1/lose \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"reason":"Example reason"}' ``` ```json { "api": "https://api.sb/shiftnote.app", "deal": { "$id": "https://api.sb/shiftnote.app/deals/deal_1", "$type": "Deal", "status": "Lost" }, "action": { "$id": "https://api.sb/shiftnote.app/actions/action_1", "operation": "Deal.lose", "status": "done" }, "links": { "self": "https://api.sb/shiftnote.app/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const deal = await $.Deal.lose({ deal: 'deal_1', reason: 'Example reason' }) ``` **CLI** ```bash npx startup-builder do Deal.lose --json '{"deal":"deal_1","reason":"Example reason"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Deal.lose({ deal: 'deal_1', reason: 'Example reason' })" } } ``` # propose URL: /business/nouns/deal/propose · Id: `verb:Deal.propose` · Call: `await $.Deal.propose({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Propose sends a Deal’s buyer a Quote they accept to place an Order. Propose sends a [Deal](/business/nouns/deal)’s buyer a [Quote](/business/nouns/quote) they accept to place an [Order](/business/nouns/order). ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `deal` | [Deal](/business/nouns/deal) | Yes | The qualified Deal. | | `quote` | [Quote](/business/nouns/quote) | Yes | The Quote to send. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `deal` | [Deal](/business/nouns/deal) | Yes | The Deal with its Quote out. | ## Effects - Emits [`Deal.proposed`](/business/events/Deal.proposed). - Performed by the [Sales Lead](/agents/sales/sales-lead). - One-way (money, customer): it waits out its delay window, and runs in the `send` and `do` modes. - Checks the discount Limit; above it, opens an Approval. - Checks each Quote line’s discount against the discount Limit’s `percent`; a deeper line holds the Quote and opens an Approval. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Deal.propose](/business/nouns/deal/propose) | | The record is not in a state that allows this Verb, so the call is refused. | [`refused`](/code/api/errors/refused) | Read the record, run the Verb that moves it to an allowed state, then retry. | [Deal.propose](/business/nouns/deal/propose) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Medium: one-way, bounded (money, customer) | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | 1 business hour, in which a watcher can pause, redirect or cancel it; then it runs. | | Limit | The spend [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) or [Mandate](/business/nouns/mandate) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Propose the latest deal with a quote. ``` **API** ```bash curl -X POST https://api.sb/quietcopy.com/deals/deal_1/propose \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"quote":"quote_1"}' ``` ```json { "api": "https://api.sb/quietcopy.com", "deal": { "$id": "https://api.sb/quietcopy.com/deals/deal_1", "$type": "Deal", "status": "Proposed" }, "action": { "$id": "https://api.sb/quietcopy.com/actions/action_1", "operation": "Deal.propose", "status": "done" }, "links": { "self": "https://api.sb/quietcopy.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const deal = await $.Deal.propose({ deal: 'deal_1', quote: 'quote_1' }) ``` **CLI** ```bash npx startup-builder do Deal.propose --json '{"deal":"deal_1","quote":"quote_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Deal.propose({ deal: 'deal_1', quote: 'quote_1' })" } } ``` # win URL: /business/nouns/deal/win · Id: `verb:Deal.win` · Call: `await $.Deal.win({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Win closes a Deal as won, which places its Order and makes the buyer a Customer. Win closes a [Deal](/business/nouns/deal) as won, which places its [Order](/business/nouns/order) and makes the buyer a [Customer](/business/nouns/customer). ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `deal` | [Deal](/business/nouns/deal) | Yes | The proposed Deal. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `order` | [Order](/business/nouns/order) | Yes | The placed Order. | | `deal` | [Deal](/business/nouns/deal) | Yes | The Deal, now won. | ## Effects - Emits [`Deal.won`](/business/events/Deal.won). - Performed by the [Sales Lead](/agents/sales/sales-lead). ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Deal.win](/business/nouns/deal/win) | | The record is not in a state that allows this Verb, so the call is refused. | [`refused`](/code/api/errors/refused) | Read the record, run the Verb that moves it to an allowed state, then retry. | [Deal.win](/business/nouns/deal/win) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Win the latest deal. ``` **API** ```bash curl -X POST https://api.sb/tutorloop.com/deals/deal_1/win \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/tutorloop.com", "order": { "$id": "https://api.sb/tutorloop.com/orders/order_1", "$type": "Order", "total": { "amount": 60, "currency": "USD" }, "status": "placed" }, "deal": { "$id": "https://api.sb/tutorloop.com/deals/deal_1", "$type": "Deal", "status": "Won" }, "action": { "$id": "https://api.sb/tutorloop.com/actions/action_1", "operation": "Deal.win", "status": "done" }, "links": { "self": "https://api.sb/tutorloop.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { order, deal } = await $.Deal.win({ deal: 'deal_1' }) ``` **CLI** ```bash npx startup-builder do Deal.win --json '{"deal":"deal_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Deal.win({ deal: 'deal_1' })" } } ``` # Decision URL: /business/nouns/decision · Id: `noun:decision` > A Decision is the immutable record of a choice: its options, the choice, the reason, who decided, and the stakes. A Decision is the immutable record of a choice: its options, the choice, the reason, who decided, and the stakes. A newer Decision supersedes it, and both stay on record. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `choice` | `text` | Yes | What was chosen. | | `reason` | `text` | Yes | Why it was chosen. | | `stakes` | `string` | No | One of `low`, `medium`, or `high`, which sets the delay window. | ## Object ```json { "$id": "https://api.sb/tutorloop.com/decisions/decision_1", "$type": "Decision", "choice": "Example choice", "reason": "Example reason", "stakes": "low" } ``` ## Relationships - A Decision **has** many [Changes](/business/nouns/change): every merged [Change](/business/nouns/change) traces back to the Decision that authorized it. `changes`, inverse [`implementsDecision`](/business/nouns/change#rel-implements-decision). - A Decision **decides** one [Thing](/business/nouns/thing): a Decision records one choice about a [Thing](/business/nouns/thing) and stays on that Thing’s record forever. `decides`, inverse [`decidedBy`](/business/nouns/thing#rel-decided-by). - A Decision **is made in** one [Meeting](/business/nouns/meeting): a [Meeting](/business/nouns/meeting) records Decisions, each with its options, choice and reason. `madeIn`, inverse [`produces`](/business/nouns/meeting#rel-produces). - A Decision **records** one [Demand Budget](/business/nouns/demand-budget): each [Demand Budget](/business/nouns/demand-budget) is committed as one Decision, read again when it closes. `records`, inverse [`recordedAs`](/business/nouns/demand-budget#rel-recorded-as). ## Lifecycle | State | Meaning | Moves to | | --- | --- | --- | | `standing` (first) | It is the choice in force. | `superseded` by [Decision.supersede](/business/nouns/decision/supersede) | | `superseded` | A newer Decision replaced it; both stay on record with the reason for the change. | None: it ends here. | ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Decision.supersede](/business/nouns/decision/supersede) | Supersede replaces a Decision with a newer one, keeping both on record with the reason for the change. | [Strategist](/agents/founding/strategist) | [`Decision.superseded`](/business/events/Decision.superseded) | None. | | [Decision.create](/business/nouns/decision/create) | Creates a Decision. Inherited from [Noun](/business/nouns/noun). | None. | `Decision.created` | Two-way: `try`, `send`, `do` | | [Decision.get](/business/nouns/decision/get) | Returns one Decision by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Decision.list](/business/nouns/decision/list) | Returns Decisions, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | A Decision is kept forever and never edited: it has no `update` or `delete`. ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Decision.create` | Yes | Yes | Yes | No | | `Decision.get` | Yes | Yes | Yes | Yes | | `Decision.list` | Yes | Yes | Yes | Yes | | `Decision.supersede` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Supersede the latest decision. ``` **API** ```bash curl -X POST https://api.sb/petpantry.shop/decisions/decision_1/supersede \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"by":"decision_1"}' ``` ```json { "api": "https://api.sb/petpantry.shop", "decision": { "$id": "https://api.sb/petpantry.shop/decisions/decision_1", "$type": "Decision", "choice": "Example choice", "reason": "Example reason" }, "action": { "$id": "https://api.sb/petpantry.shop/actions/action_1", "operation": "Decision.supersede", "status": "done" }, "links": { "self": "https://api.sb/petpantry.shop/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const decision = await $.Decision.supersede({ decision: 'decision_1', by: 'decision_1' }) ``` **CLI** ```bash npx startup-builder do Decision.supersede --json '{"decision":"decision_1","by":"decision_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Decision.supersede({ decision: 'decision_1', by: 'decision_1' })" } } ``` ## Example The [Founder](/agents/founding/founder) picks usage pricing over per-seat pricing. The Decision records both options, `choice: usage`, the `reason` ("[Customers](/business/nouns/customer) already pay per call"), and `stakes` of $40,000 a year. # supersede URL: /business/nouns/decision/supersede · Id: `verb:Decision.supersede` · Call: `await $.Decision.supersede({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Supersede replaces a Decision with a newer one, keeping both on record with the reason for the change. Supersede replaces a [Decision](/business/nouns/decision) with a newer one, keeping both on record with the reason for the change. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `decision` | [Decision](/business/nouns/decision) | Yes | The Decision to replace. | | `by` | [Decision](/business/nouns/decision) | Yes | The newer Decision. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `decision` | [Decision](/business/nouns/decision) | Yes | The superseded Decision. | ## Effects - Emits [`Decision.superseded`](/business/events/Decision.superseded). - Performed by the [Strategist](/agents/founding/strategist). ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Decision.supersede](/business/nouns/decision/supersede) | | The record is not in a state that allows this Verb, so the call is refused. | [`refused`](/code/api/errors/refused) | Read the record, run the Verb that moves it to an allowed state, then retry. | [Decision.supersede](/business/nouns/decision/supersede) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Supersede the latest decision. ``` **API** ```bash curl -X POST https://api.sb/petpantry.shop/decisions/decision_1/supersede \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"by":"decision_1"}' ``` ```json { "api": "https://api.sb/petpantry.shop", "decision": { "$id": "https://api.sb/petpantry.shop/decisions/decision_1", "$type": "Decision", "choice": "Example choice", "reason": "Example reason" }, "action": { "$id": "https://api.sb/petpantry.shop/actions/action_1", "operation": "Decision.supersede", "status": "done" }, "links": { "self": "https://api.sb/petpantry.shop/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const decision = await $.Decision.supersede({ decision: 'decision_1', by: 'decision_1' }) ``` **CLI** ```bash npx startup-builder do Decision.supersede --json '{"decision":"decision_1","by":"decision_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Decision.supersede({ decision: 'decision_1', by: 'decision_1' })" } } ``` # Demand Budget URL: /business/nouns/demand-budget · Id: `noun:demand-budget` > A Demand Budget is the money a founder commits each month to demand Plays, recorded as a Decision with a target and a stop rule. A Demand Budget is the money a founder commits each month to demand [Plays](/business/nouns/play), recorded as a [Decision](/business/nouns/decision) with a target and a stop rule. A [Startup](/business/nouns/startup) without one runs at $0, on free Plays only. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `amount` | `money` | Yes | The monthly spend it funds; zero is the default. | | `tier` | `string` | Yes | One of `$0`, `$100`, `$1k`, `$10k` or `$100k`: the highest tier at or below the amount, whose Play mix it buys. | | `target` | `string` | Yes | The Metric value the spend must reach, such as cost per first Order under $40. | | `stopRule` | `string` | Yes | The reading that closes the budget, such as acquisition cost above margin for two weeks. | | `until` | `date` | No | The last day the budget runs before its Decision is read. | | `status` | `string` | Yes | One of `Open`, `Stopped` or `Closed`. A closed budget is kept with its Evidence. | ## Object ```json { "$id": "https://api.sb/routewise.dev/demand-budgets/demand_budget_1", "$type": "DemandBudget", "amount": { "amount": 25, "currency": "USD" }, "tier": "$0", "target": "Example target", "stopRule": "Example stop rule", "until": "2026-10-22", "status": "Open" } ``` ## Relationships - A Demand Budget **is allocated by** many [Play Mixes](/business/nouns/play-mix): each [Play Mix](/business/nouns/play-mix) version splits one Demand Budget across its paid [Plays](/business/nouns/play). `allocatedBy`, inverse [`allocates`](/business/nouns/play-mix#rel-allocates). - A Demand Budget **is funded by** one [Startup](/business/nouns/startup): a [Startup](/business/nouns/startup) commits monthly Demand Budgets, each with a target and a stop rule. `fundedBy`, inverse [`funds`](/business/nouns/startup#rel-funds). - A Demand Budget **pays** many [Plays](/business/nouns/play): a Demand Budget’s spend buys demand [Plays](/business/nouns/play). `pays`, inverse [`paidBy`](/business/nouns/play#rel-paid-by). - A Demand Budget **is recorded as** one [Decision](/business/nouns/decision): each Demand Budget is committed as one [Decision](/business/nouns/decision), read again when it closes. `recordedAs`, inverse [`records`](/business/nouns/decision#rel-records). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [DemandBudget.create](/business/nouns/demand-budget/create) | Creates a Demand Budget. Inherited from [Noun](/business/nouns/noun). | None. | `DemandBudget.created` | Two-way: `try`, `send`, `do` | | [DemandBudget.get](/business/nouns/demand-budget/get) | Returns one Demand Budget by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [DemandBudget.list](/business/nouns/demand-budget/list) | Returns Demand Budgets, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [DemandBudget.update](/business/nouns/demand-budget/update) | Changes the given properties of a Demand Budget. Inherited from [Noun](/business/nouns/noun). | None. | `DemandBudget.updated` | Two-way: `try`, `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `DemandBudget.create` | Yes | Yes | Yes | No | | `DemandBudget.get` | Yes | Yes | Yes | Yes | | `DemandBudget.list` | Yes | Yes | Yes | Yes | | `DemandBudget.update` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Add a demand budget to TutorLoop. ``` **API** ```bash curl -X POST https://api.sb/tutorloop.com/demand-budgets \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"amount":{"amount":60,"currency":"USD"},"tier":"$0","target":"Example target","stopRule":"Example stop rule"}' ``` ```json { "api": "https://api.sb/tutorloop.com", "demandBudget": { "$id": "https://api.sb/tutorloop.com/demand-budgets/demand_budget_1", "$type": "DemandBudget", "amount": { "amount": 60, "currency": "USD" }, "tier": "$0", "target": "Example target", "stopRule": "Example stop rule" }, "action": { "$id": "https://api.sb/tutorloop.com/actions/action_1", "operation": "DemandBudget.create", "status": "done" }, "links": { "self": "https://api.sb/tutorloop.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const demandBudget = await $.DemandBudget.create({ amount: { amount: 60, currency: 'USD' }, tier: '$0', target: 'Example target', stopRule: 'Example stop rule' }) ``` **CLI** ```bash npx startup-builder do DemandBudget.create --json '{"amount":{"amount":60,"currency":"USD"},"tier":"$0","target":"Example target","stopRule":"Example stop rule"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.DemandBudget.create({ amount: { amount: 60, currency: 'USD' }, tier: '$0', target: 'Example target', stopRule: 'Example stop rule' })" } } ``` ## Example A founder funds a $1,000 Demand Budget for a Startup selling a scheduling app to dental offices. Its target is cost per first [Order](/business/nouns/order) under $90, and its stop rule closes it if cost runs higher for two weeks. [Marketing](/workflows/marketing/demand-budgets) spends it on one paid search [Campaign](/business/nouns/campaign). # accept URL: /business/nouns/dispute/accept · Id: `verb:Dispute.accept` · Call: `await $.Dispute.accept({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Accept concedes an open Dispute without contest, so the buyer keeps the held amount and the Dispute closes. Accept concedes an open [Dispute](/business/nouns/dispute) without contest, so the buyer keeps the held amount and the Dispute closes. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `dispute` | [Dispute](/business/nouns/dispute) | Yes | The open Dispute. | | `reason` | `text` | Yes | Why contesting is not worth it, such as a fraud chargeback with no delivery Evidence. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `dispute` | [Dispute](/business/nouns/dispute) | Yes | The closed Dispute, decided for the buyer. | ## Effects - Emits [`Dispute.accepted`](/business/events/Dispute.accepted). - Performed by the [Billing Specialist](/agents/finance/billing-specialist). - One-way (money): it waits out its delay window, and runs in the `send` and `do` modes. - For a `chargeback`, tells the card issuer through Stripe; the disputed amount and the fee are lost. - Records a Decision with its reason. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Dispute.accept](/business/nouns/dispute/accept) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Medium: one-way, bounded (money) | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | 1 business hour, in which a watcher can pause, redirect or cancel it; then it runs. | | Limit | The spend [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) or [Mandate](/business/nouns/mandate) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Accept the latest dispute. ``` **API** ```bash curl -X POST https://api.sb/tutorloop.com/disputes/dispute_1/accept \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"reason":"Example reason"}' ``` ```json { "api": "https://api.sb/tutorloop.com", "dispute": { "$id": "https://api.sb/tutorloop.com/disputes/dispute_1", "$type": "Dispute", "kind": "chargeback", "status": "open", "held": { "amount": 60, "currency": "USD" }, "reason": "Example reason" }, "action": { "$id": "https://api.sb/tutorloop.com/actions/action_1", "operation": "Dispute.accept", "status": "done" }, "links": { "self": "https://api.sb/tutorloop.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const dispute = await $.Dispute.accept({ dispute: 'dispute_1', reason: 'Example reason' }) ``` **CLI** ```bash npx startup-builder do Dispute.accept --json '{"dispute":"dispute_1","reason":"Example reason"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Dispute.accept({ dispute: 'dispute_1', reason: 'Example reason' })" } } ``` # answer URL: /business/nouns/dispute/answer · Id: `verb:Dispute.answer` · Call: `await $.Dispute.answer({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Answer submits the seller’s Evidence on an open Dispute before its deadline: the contract, the delivered work, and its verdicts. Answer submits the seller’s [Evidence](/business/nouns/evidence) on an open [Dispute](/business/nouns/dispute) before its deadline: the contract, the delivered work, and its verdicts. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `dispute` | [Dispute](/business/nouns/dispute) | Yes | The open Dispute. | | `evidence` | list of [Evidence](/business/nouns/evidence) | Yes | The records that show the promise was kept. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `dispute` | [Dispute](/business/nouns/dispute) | Yes | The answered Dispute. | ## Effects - Emits [`Dispute.answered`](/business/events/Dispute.answered). - Performed by the [Customer Lead](/agents/customer/customer-lead). - One-way (money): it waits out its delay window, and runs in the `send` and `do` modes. - Freezes the submitted Evidence; later changes to the work do not alter it. - For a chargeback, sends the Evidence to the card issuer through the payment account. - Builds the Evidence from records: the Agreement Version the buyer accepted, the delivery Evidence and the Actions on the Order. - A `chargeback` gets one submission; an answered `inquiry`, or a full refund, closes it with no fee. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Dispute.answer](/business/nouns/dispute/answer) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Medium: one-way, bounded (money) | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | 1 business hour, in which a watcher can pause, redirect or cancel it; then it runs. | | Limit | The spend [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) or [Mandate](/business/nouns/mandate) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Answer the latest dispute with evidence. ``` **API** ```bash curl -X POST https://api.sb/kilnbakery.com/disputes/dispute_1/answer \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"evidence":["evidence_1"]}' ``` ```json { "api": "https://api.sb/kilnbakery.com", "dispute": { "$id": "https://api.sb/kilnbakery.com/disputes/dispute_1", "$type": "Dispute", "kind": "chargeback", "status": "answered", "held": { "amount": 9, "currency": "USD" }, "reason": "Example reason" }, "action": { "$id": "https://api.sb/kilnbakery.com/actions/action_1", "operation": "Dispute.answer", "status": "done" }, "links": { "self": "https://api.sb/kilnbakery.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const dispute = await $.Dispute.answer({ dispute: 'dispute_1', evidence: ['evidence_1'] }) ``` **CLI** ```bash npx startup-builder do Dispute.answer --json '{"dispute":"dispute_1","evidence":["evidence_1"]}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Dispute.answer({ dispute: 'dispute_1', evidence: ['evidence_1'] })" } } ``` Guides that call it: [Answer a dispute](/systems/finance/answer-a-dispute). # appeal URL: /business/nouns/dispute/appeal · Id: `verb:Dispute.appeal` · Call: `await $.Dispute.appeal({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Appeal asks for one review of a decided Dispute by a Worker who took no part in the first decision. Appeal asks for one review of a decided [Dispute](/business/nouns/dispute) by a [Worker](/business/nouns/worker) who took no part in the first decision. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `dispute` | [Dispute](/business/nouns/dispute) | Yes | The decided Dispute. | | `reason` | `text` | Yes | What the first decision got wrong. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `dispute` | [Dispute](/business/nouns/dispute) | Yes | The appealed Dispute. | ## Effects - Emits [`Dispute.appealed`](/business/events/Dispute.appealed). - Performed by the [Billing Specialist](/agents/finance/billing-specialist). - One-way (money): it waits out its delay window, and runs in the `send` and `do` modes. - Keeps the held amount held until the appeal is decided. - Allows one appeal per Dispute; the second decision is final. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Dispute.appeal](/business/nouns/dispute/appeal) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Medium: one-way, bounded (money) | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | 1 business hour, in which a watcher can pause, redirect or cancel it; then it runs. | | Limit | The spend [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) or [Mandate](/business/nouns/mandate) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Appeal the latest dispute. ``` **API** ```bash curl -X POST https://api.sb/patentpad.com/disputes/dispute_1/appeal \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"reason":"Example reason"}' ``` ```json { "api": "https://api.sb/patentpad.com", "dispute": { "$id": "https://api.sb/patentpad.com/disputes/dispute_1", "$type": "Dispute", "kind": "chargeback", "status": "appealed", "held": { "amount": 499, "currency": "USD" }, "reason": "Example reason" }, "action": { "$id": "https://api.sb/patentpad.com/actions/action_1", "operation": "Dispute.appeal", "status": "done" }, "links": { "self": "https://api.sb/patentpad.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const dispute = await $.Dispute.appeal({ dispute: 'dispute_1', reason: 'Example reason' }) ``` **CLI** ```bash npx startup-builder do Dispute.appeal --json '{"dispute":"dispute_1","reason":"Example reason"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Dispute.appeal({ dispute: 'dispute_1', reason: 'Example reason' })" } } ``` # decide URL: /business/nouns/dispute/decide · Id: `verb:Dispute.decide` · Call: `await $.Dispute.decide({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Decide rules on an answered Dispute for the buyer, the seller, or a split, and releases or returns the held amount. Decide rules on an answered [Dispute](/business/nouns/dispute) for the buyer, the seller, or a split, and releases or returns the held amount. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `dispute` | [Dispute](/business/nouns/dispute) | Yes | The answered Dispute. | | `decision` | `string` | Yes | One of `buyer`, `seller`, or `split`. | | `reason` | `text` | Yes | Why, citing the Evidence and the contract term it turns on. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `dispute` | [Dispute](/business/nouns/dispute) | Yes | The decided Dispute. | ## Effects - Emits [`Dispute.decided`](/business/events/Dispute.decided). - Performed by the [Billing Specialist](/agents/finance/billing-specialist). - One-way (money, customer): it waits out its delay window, and runs in the `send` and `do` modes. - Posts the reversing or releasing Entries for the held amount. - Records a Decision with its reason. - For a chargeback, records the card issuer’s ruling as it arrives. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Dispute.decide](/business/nouns/dispute/decide) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Medium: one-way, bounded (money, customer) | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | 1 business hour, in which a watcher can pause, redirect or cancel it; then it runs. | | Limit | The spend [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) or [Mandate](/business/nouns/mandate) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Decide the latest dispute. ``` **API** ```bash curl -X POST https://api.sb/quietcopy.com/disputes/dispute_1/decide \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"decision":"buyer","reason":"Example reason"}' ``` ```json { "api": "https://api.sb/quietcopy.com", "dispute": { "$id": "https://api.sb/quietcopy.com/disputes/dispute_1", "$type": "Dispute", "kind": "chargeback", "status": "decided", "held": { "amount": 39, "currency": "USD" }, "reason": "Example reason" }, "action": { "$id": "https://api.sb/quietcopy.com/actions/action_1", "operation": "Dispute.decide", "status": "done" }, "links": { "self": "https://api.sb/quietcopy.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const dispute = await $.Dispute.decide({ dispute: 'dispute_1', decision: 'buyer', reason: 'Example reason' }) ``` **CLI** ```bash npx startup-builder do Dispute.decide --json '{"dispute":"dispute_1","decision":"buyer","reason":"Example reason"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Dispute.decide({ dispute: 'dispute_1', decision: 'buyer', reason: 'Example reason' })" } } ``` # Dispute URL: /business/nouns/dispute · Id: `noun:dispute` > A Dispute is a contested payment or delivery, such as a chargeback, a rejected Service outcome, or a buyer’s claim against a Supplier. A Dispute is a contested payment or delivery, such as a chargeback, a rejected [Service](/business/nouns/service) outcome, or a buyer’s claim against a [Supplier](/business/nouns/supplier). ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `kind` | `string` | Yes | One of `chargeback`, `outcome`, or `marketplace`. | | `status` | `string` | Yes | One of `open`, `answered`, `decided`, `appealed`, or `closed`. | | `held` | `money` | Yes | The amount held from the seller until the Dispute closes. | | `reason` | `text` | Yes | What the buyer says fell short, in their words. | | `answerBy` | `datetime` | No | When the seller’s answer is due; a missed deadline decides for the buyer. | | `decision` | `string` | No | One of `buyer`, `seller`, or `split`, with the amounts each side keeps. | | `decidedBy` | `string` | Yes | `issuer` (the cardholder’s bank) for a `chargeback`; `worker`, uninvolved in the Order, for an `outcome` or `marketplace` Dispute. | | `fee` | `money` | No | The card network’s fee on a `chargeback`, debited with the held amount when it opens. | ## Object ```json { "$id": "https://api.sb/tutorloop.com/disputes/dispute_1", "$type": "Dispute", "kind": "chargeback", "status": "open", "held": { "amount": 60, "currency": "USD" }, "reason": "Example reason", "answerBy": "2026-10-22T12:00:00Z", "decision": "buyer", "decidedBy": "issuer", "fee": { "amount": 60, "currency": "USD" } } ``` ## Relationships - A Dispute **cites** many pieces of [Evidence](/business/nouns/evidence): the [Evidence](/business/nouns/evidence) each side submits on the Dispute, frozen once submitted. `cites`, inverse [`citedBy`](/business/nouns/evidence#rel-cited-by). - A Dispute **contests** one [Order](/business/nouns/order): the [Order](/business/nouns/order) whose delivery or charge the Dispute contests. `contests`, inverse [`disputes`](/business/nouns/order#rel-disputes). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Dispute.accept](/business/nouns/dispute/accept) | Accept concedes an open Dispute without contest, so the buyer keeps the held amount and the Dispute closes. | [Billing Specialist](/agents/finance/billing-specialist) | [`Dispute.accepted`](/business/events/Dispute.accepted) | One-way (money): `send`, `do` | | [Dispute.answer](/business/nouns/dispute/answer) | Answer submits the seller’s Evidence on an open Dispute before its deadline: the contract, the delivered work, and its verdicts. | [Customer Lead](/agents/customer/customer-lead) | [`Dispute.answered`](/business/events/Dispute.answered) | One-way (money): `send`, `do` | | [Dispute.appeal](/business/nouns/dispute/appeal) | Appeal asks for one review of a decided Dispute by a Worker who took no part in the first decision. | [Billing Specialist](/agents/finance/billing-specialist) | [`Dispute.appealed`](/business/events/Dispute.appealed) | One-way (money): `send`, `do` | | [Dispute.decide](/business/nouns/dispute/decide) | Decide rules on an answered Dispute for the buyer, the seller, or a split, and releases or returns the held amount. | [Billing Specialist](/agents/finance/billing-specialist) | [`Dispute.decided`](/business/events/Dispute.decided) | One-way (money, customer): `send`, `do` | | [Dispute.get](/business/nouns/dispute/get) | Returns one Dispute by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Dispute.list](/business/nouns/dispute/list) | Returns Disputes, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | A Dispute is kept forever and never edited: it has no `update` or `delete`. ## Events Events no Verb emits. Each Verb’s Event is in the Verbs table above; every Event is delivered in the same shape. ### Dispute.opened A card issuer opened a Dispute against a charge, and the rail holds the disputed amount. Raised by the rail. | Field | Type | Required | Description | | --- | --- | --- | --- | | `name` | `string` | Yes | `Dispute.opened`. | | `at` | `datetime` | Yes | When it happened. | | `seq` | `integer` | No | Its position in the namespace, one more than the Event before; any seq is a cursor into the history. | | `data` | `json` | Yes | The Thing as the Action left it. | | `data.dispute` | [Dispute](/business/nouns/dispute) | Yes | The Dispute as the change left it. | | `data.dispute.kind` | `string` | Yes | One of `chargeback`, `outcome`, or `marketplace`. | | `data.dispute.status` | `string` | Yes | One of `open`, `answered`, `decided`, `appealed`, or `closed`. | | `data.dispute.held` | `money` | Yes | The amount held from the seller until the Dispute closes. | | `data.dispute.reason` | `text` | Yes | What the buyer says fell short, in their words. | | `data.dispute.answerBy` | `datetime` | No | When the seller’s answer is due; a missed deadline decides for the buyer. | | `data.dispute.decision` | `string` | No | One of `buyer`, `seller`, or `split`, with the amounts each side keeps. | | `data.dispute.decidedBy` | `string` | Yes | `issuer` (the cardholder’s bank) for a `chargeback`; `worker`, uninvolved in the Order, for an `outcome` or `marketplace` Dispute. | | `data.dispute.fee` | `money` | No | The card network’s fee on a `chargeback`, debited with the held amount when it opens. | | `data.transaction` | [Transaction](/business/nouns/transaction) | Yes | The disputed charge. | ```json { "$id": "https://api.sb/tutorloop.com/events/event_1", "$type": "Event", "name": "Dispute.opened", "at": "2026-10-22T12:00:00Z", "data": { "dispute": { "$id": "https://api.sb/tutorloop.com/disputes/dispute_1", "$type": "Dispute", "kind": "chargeback", "status": "open", "held": { "amount": 60, "currency": "USD" }, "reason": "Example reason", "answerBy": "2026-10-22T12:00:00Z", "decision": "buyer", "decidedBy": "issuer", "fee": { "amount": 60, "currency": "USD" } }, "transaction": { "$id": "https://api.sb/tutorloop.com/transactions/transaction_1", "$type": "Transaction", "kind": "charge", "amount": { "amount": 60, "currency": "USD" } } }, "seq": 1 } ``` ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Dispute.get` | Yes | Yes | Yes | Yes | | `Dispute.list` | Yes | Yes | Yes | Yes | | `Dispute.accept` | Yes | No | No | No | | `Dispute.answer` | Yes | No | No | No | | `Dispute.appeal` | Yes | No | No | No | | `Dispute.decide` | Yes | No | No | No | ## Stripe **Dispute** (`dispute`), for a Dispute whose `kind` is `chargeback`. The source of truth is Stripe: db.sb mirrors it, written only from Stripe’s webhooks. | Property | Stripe field | Source of truth | | --- | --- | --- | | `held` | `amount` | Stripe | | `reason` | `reason` | Stripe | | `status` | `status` | Stripe | | `answerBy` | `evidence_details.due_by` | Stripe | | `fee` | `balance_transactions[].fee` | Stripe | ## Call it **Ask** ```text Answer the latest dispute with evidence. ``` **API** ```bash curl -X POST https://api.sb/kilnbakery.com/disputes/dispute_1/answer \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"evidence":["evidence_1"]}' ``` ```json { "api": "https://api.sb/kilnbakery.com", "dispute": { "$id": "https://api.sb/kilnbakery.com/disputes/dispute_1", "$type": "Dispute", "kind": "chargeback", "status": "answered", "held": { "amount": 9, "currency": "USD" }, "reason": "Example reason" }, "action": { "$id": "https://api.sb/kilnbakery.com/actions/action_1", "operation": "Dispute.answer", "status": "done" }, "links": { "self": "https://api.sb/kilnbakery.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const dispute = await $.Dispute.answer({ dispute: 'dispute_1', evidence: ['evidence_1'] }) ``` **CLI** ```bash npx startup-builder do Dispute.answer --json '{"dispute":"dispute_1","evidence":["evidence_1"]}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Dispute.answer({ dispute: 'dispute_1', evidence: ['evidence_1'] })" } } ``` ## Example A store disputes a catalog cleanup [Order](/business/nouns/order) because 40 products landed in the wrong category. The Dispute holds the fee, the fix runs, and the store confirms the redelivery. The Dispute closes with no decision, and the fee is earned. # DNS Record URL: /business/nouns/dns-record · Id: `noun:dns-record` > A DNS Record is one DNS answer of a Domain: its type, name and value, who owns it, and what the world last answered. A DNS Record is one DNS answer of a [Domain](/business/nouns/domain): its type, name and value, who owns it, and what the world last answered. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `type` | `string` | Yes | The record type, written in lowercase. | | `name` | `string` | Yes | The label under the Domain, such as `@`, `www` or `_dmarc`. | | `value` | `string` | Yes | The declared answer. | | `owner` | `string` | Yes | `platform` records serve the Site, authenticate mail and validate certificates, and refuse edits; `startup` records change freely. | | `observed` | `string` | No | What public DNS answered at the last daily check. | | `status` | `string` | No | `dangling` means the target no longer answers, the opening for a subdomain takeover; `removed` means it no longer answers at all. | ## Object ```json { "$id": "https://api.sb/ledgerlark.com/dns-records/dns_record_1", "$type": "DNSRecord", "type": "a", "name": "_dmarc", "value": "192.0.2.10", "owner": "platform", "observed": "192.0.2.10", "status": "missing" } ``` ## Relationships - A DNS Record **answers for** one [Domain](/business/nouns/domain): a [Domain](/business/nouns/domain) answers DNS from its records; each record belongs to one Domain. `answersFor`, inverse [`records`](/business/nouns/domain#rel-records). ## Lifecycle | State | Meaning | Moves to | | --- | --- | --- | | `missing` (first) | Declared, and public DNS does not answer it yet; a new record waits here while it propagates. | `ok` on [`DNSRecord.checked`](/business/nouns/dns-record#dnsrecordchecked) when public DNS answers the declared value; `dangling` on [`DNSRecord.checked`](/business/nouns/dns-record#dnsrecordchecked) when the record answers and its target does not; `removed` by [DNSRecord.remove](/business/nouns/dns-record/remove) | | `ok` | Public DNS answers the declared value. | `missing` on [`DNSRecord.checked`](/business/nouns/dns-record#dnsrecordchecked) when public DNS gives no answer; `drifted` on [`DNSRecord.checked`](/business/nouns/dns-record#dnsrecordchecked) when public DNS answers another value; `dangling` on [`DNSRecord.checked`](/business/nouns/dns-record#dnsrecordchecked) when the record answers and its target does not; `removed` by [DNSRecord.remove](/business/nouns/dns-record/remove) | | `drifted` | Public DNS answers a value other than the declared one, changed outside a Change. | `ok` on [`DNSRecord.checked`](/business/nouns/dns-record#dnsrecordchecked) when public DNS answers the declared value again; `missing` by [DNSRecord.set](/business/nouns/dns-record/set); `removed` by [DNSRecord.remove](/business/nouns/dns-record/remove) | | `dangling` | It points at a target that no longer answers, which opens the name to takeover. | `ok` on [`DNSRecord.checked`](/business/nouns/dns-record#dnsrecordchecked) when its target answers again; `missing` by [DNSRecord.set](/business/nouns/dns-record/set); `removed` by [DNSRecord.remove](/business/nouns/dns-record/remove) | | `removed` | It no longer answers; its history stays, and reverting its Change restores it. | None: it ends here. | ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [DNSRecord.remove](/business/nouns/dns-record/remove) | Remove stops a Startup-owned DNS Record from answering; its history stays and a revert restores it. | [Reliability Engineer](/agents/engineering/reliability-engineer) | [`DNSRecord.removed`](/business/events/DNSRecord.removed) | Two-way: `try`, `send`, `do` | | [DNSRecord.set](/business/nouns/dns-record/set) | Set adds or changes a Startup-owned DNS Record through a Change, previewed against what the Domain answers today. | [Reliability Engineer](/agents/engineering/reliability-engineer) | [`DNSRecord.set`](/business/events/DNSRecord.set) | Two-way: `try`, `send`, `do` | | [DNSRecord.get](/business/nouns/dns-record/get) | Returns one DNS Record by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [DNSRecord.list](/business/nouns/dns-record/list) | Returns DNS Records, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | A DNS Record is kept forever and never edited: it has no `update` or `delete`. ## Events Events no Verb emits. Each Verb’s Event is in the Verbs table above; every Event is delivered in the same shape. ### DNSRecord.checked The daily check read what public DNS answers for a DNS Record and compared it with the declared value. Raised by a clock. | Field | Type | Required | Description | | --- | --- | --- | --- | | `name` | `string` | Yes | `DNSRecord.checked`. | | `at` | `datetime` | Yes | When it happened. | | `seq` | `integer` | No | Its position in the namespace, one more than the Event before; any seq is a cursor into the history. | | `data` | `json` | Yes | The Thing as the Action left it. | | `data.dnsRecord` | [DNS Record](/business/nouns/dns-record) | Yes | The DNS Record as the change left it. | | `data.dnsRecord.type` | `string` | Yes | The record type, written in lowercase. | | `data.dnsRecord.name` | `string` | Yes | The label under the Domain, such as `@`, `www` or `_dmarc`. | | `data.dnsRecord.value` | `string` | Yes | The declared answer. | | `data.dnsRecord.owner` | `string` | Yes | `platform` records serve the Site, authenticate mail and validate certificates, and refuse edits; `startup` records change freely. | | `data.dnsRecord.observed` | `string` | No | What public DNS answered at the last daily check. | | `data.dnsRecord.status` | `string` | No | `dangling` means the target no longer answers, the opening for a subdomain takeover; `removed` means it no longer answers at all. | ```json { "$id": "https://api.sb/ledgerlark.com/events/event_1", "$type": "Event", "name": "DNSRecord.checked", "at": "2026-10-22T12:00:00Z", "data": { "dnsRecord": { "$id": "https://api.sb/ledgerlark.com/dns-records/dns_record_1", "$type": "DNSRecord", "type": "a", "name": "_dmarc", "value": "192.0.2.10", "owner": "platform", "observed": "192.0.2.10", "status": "missing" } }, "seq": 1 } ``` ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `DNSRecord.get` | Yes | Yes | Yes | Yes | | `DNSRecord.list` | Yes | Yes | Yes | Yes | | `DNSRecord.remove` | Yes | Yes | Yes | No | | `DNSRecord.set` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Set the latest DNS record with a domain. ``` **API** ```bash curl -X POST https://api.sb/tutorloop.com/dns-records/set \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"domain":"domain_1","type":"a","name":"TutorLoop","value":"Example value"}' ``` ```json { "api": "https://api.sb/tutorloop.com", "record": { "$id": "https://api.sb/tutorloop.com/dns-records/dns_record_1", "$type": "DNSRecord", "type": "a", "name": "_dmarc", "value": "192.0.2.10", "owner": "platform" }, "action": { "$id": "https://api.sb/tutorloop.com/actions/action_1", "operation": "DNSRecord.set", "status": "done" }, "links": { "self": "https://api.sb/tutorloop.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const record = await $.DNSRecord.set({ domain: 'domain_1', type: 'a', name: 'TutorLoop', value: 'Example value' }) ``` **CLI** ```bash npx startup-builder do DNSRecord.set --json '{"domain":"domain_1","type":"a","name":"TutorLoop","value":"Example value"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.DNSRecord.set({ domain: 'domain_1', type: 'a', name: 'TutorLoop', value: 'Example value' })" } } ``` ## Example ```json { "$type": "DNSRecord", "type": "cname", "name": "www", "value": "fieldnotes.helpdesk.example", "owner": "startup", "observed": "NXDOMAIN", "status": "dangling" } ``` # remove URL: /business/nouns/dns-record/remove · Id: `verb:DNSRecord.remove` · Call: `await $.DNSRecord.remove({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Remove stops a Startup-owned DNS Record from answering; its history stays and a revert restores it. Remove stops a [Startup](/business/nouns/startup)-owned [DNS Record](/business/nouns/dns-record) from answering; its history stays and a revert restores it. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `record` | [DNS Record](/business/nouns/dns-record) | Yes | The DNS Record to stop. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `record` | [DNS Record](/business/nouns/dns-record) | Yes | The stopped DNS Record. | ## Effects - Emits [`DNSRecord.removed`](/business/events/DNSRecord.removed). - Performed by the [Reliability Engineer](/agents/engineering/reliability-engineer). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Refuses a record the platform owns. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [DNSRecord.remove](/business/nouns/dns-record/remove) | | A record the platform owns | [`refused`](/code/api/errors/refused) | Clear what the check names, then call it again. | [DNSRecord.remove](/business/nouns/dns-record/remove) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Remove the latest DNS record. ``` **API** ```bash curl -X POST https://api.sb/petpantry.shop/dns-records/dns_record_1/remove \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/petpantry.shop", "record": { "$id": "https://api.sb/petpantry.shop/dns-records/dns_record_1", "$type": "DNSRecord", "type": "a", "name": "_dmarc", "value": "192.0.2.10", "owner": "platform" }, "action": { "$id": "https://api.sb/petpantry.shop/actions/action_1", "operation": "DNSRecord.remove", "status": "done" }, "links": { "self": "https://api.sb/petpantry.shop/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const record = await $.DNSRecord.remove({ record: 'dns_record_1' }) ``` **CLI** ```bash npx startup-builder do DNSRecord.remove --json '{"record":"dns_record_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.DNSRecord.remove({ record: 'dns_record_1' })" } } ``` # set URL: /business/nouns/dns-record/set · Id: `verb:DNSRecord.set` · Call: `await $.DNSRecord.set({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Set adds or changes a Startup-owned DNS Record through a Change, previewed against what the Domain answers today. Set adds or changes a [Startup](/business/nouns/startup)-owned [DNS Record](/business/nouns/dns-record) through a [Change](/business/nouns/change), previewed against what the [Domain](/business/nouns/domain) answers today. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `domain` | [Domain](/business/nouns/domain) | Yes | The Domain the record answers for. | | `type` | `string` | Yes | The record type. | | `name` | `string` | Yes | The label, such as `@` or `_dmarc`. | | `value` | `string` | Yes | The answer. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `record` | [DNS Record](/business/nouns/dns-record) | Yes | The DNS Record, with its status. | ## Effects - Emits [`DNSRecord.set`](/business/events/DNSRecord.set). - Performed by the [Reliability Engineer](/agents/engineering/reliability-engineer). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Refuses a record the platform owns. - A revert of its Change restores the previous answer. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [DNSRecord.set](/business/nouns/dns-record/set) | | A record the platform owns | [`refused`](/code/api/errors/refused) | Clear what the check names, then call it again. | [DNSRecord.set](/business/nouns/dns-record/set) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Set the latest DNS record with a domain. ``` **API** ```bash curl -X POST https://api.sb/tutorloop.com/dns-records/set \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"domain":"domain_1","type":"a","name":"TutorLoop","value":"Example value"}' ``` ```json { "api": "https://api.sb/tutorloop.com", "record": { "$id": "https://api.sb/tutorloop.com/dns-records/dns_record_1", "$type": "DNSRecord", "type": "a", "name": "_dmarc", "value": "192.0.2.10", "owner": "platform" }, "action": { "$id": "https://api.sb/tutorloop.com/actions/action_1", "operation": "DNSRecord.set", "status": "done" }, "links": { "self": "https://api.sb/tutorloop.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const record = await $.DNSRecord.set({ domain: 'domain_1', type: 'a', name: 'TutorLoop', value: 'Example value' }) ``` **CLI** ```bash npx startup-builder do DNSRecord.set --json '{"domain":"domain_1","type":"a","name":"TutorLoop","value":"Example value"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.DNSRecord.set({ domain: 'domain_1', type: 'a', name: 'TutorLoop', value: 'Example value' })" } } ``` # Document URL: /business/nouns/document · Id: `noun:document` > A Document is structured, versioned material in one of three forms, a document, a deck, or a sheet, rendered to any format. A Document is structured, versioned material in one of three forms, a document, a deck, or a sheet, rendered to any format. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `form` | `string` | Yes | One of `document`, `deck`, or `sheet`. | ## Object ```json { "$id": "https://api.sb/routewise.dev/documents/document_1", "$type": "Document", "form": "document" } ``` ## Relationships - A Document **exports to** many [Files](/business/nouns/file): each rendering of a Document to a format, such as PDF, is stored as a [File](/business/nouns/file). `exportsTo`, inverse [`exportOf`](/business/nouns/file#rel-export-of). - A Document **is generated from** one [Template](/business/nouns/template): a [Template](/business/nouns/template) fills its variables from the graph to generate a Document, such as a proposal or an invoice. `generatedFrom`, inverse [`generates`](/business/nouns/template#rel-generates). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Document.render](/business/nouns/document/render) | Render produces a file from a Document in the format the reader asks for. | [Agent](/business/nouns/agent) | [`Document.rendered`](/business/events/Document.rendered) | None. | | [Document.create](/business/nouns/document/create) | Creates a Document. Inherited from [Noun](/business/nouns/noun). | None. | `Document.created` | Two-way: `try`, `send`, `do` | | [Document.get](/business/nouns/document/get) | Returns one Document by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Document.list](/business/nouns/document/list) | Returns Documents, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Document.update](/business/nouns/document/update) | Changes the given properties of a Document. Inherited from [Noun](/business/nouns/noun). | None. | `Document.updated` | Two-way: `try`, `send`, `do` | | [Document.delete](/business/nouns/document/delete) | Deletes a Document; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Document.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Document.create` | Yes | Yes | Yes | No | | `Document.get` | Yes | Yes | Yes | Yes | | `Document.list` | Yes | Yes | Yes | Yes | | `Document.update` | Yes | Yes | Yes | No | | `Document.delete` | Yes | Yes | Yes | No | | `Document.render` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Render the latest document. ``` **API** ```bash curl -X POST https://api.sb/ledgerlark.com/documents/document_1/render \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"format":"Example format"}' ``` ```json { "api": "https://api.sb/ledgerlark.com", "file": "https://ledgerlark.com", "document": { "$id": "https://api.sb/ledgerlark.com/documents/document_1", "$type": "Document", "form": "document" }, "action": { "$id": "https://api.sb/ledgerlark.com/actions/action_1", "operation": "Document.render", "status": "done" }, "links": { "self": "https://api.sb/ledgerlark.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { file, document } = await $.Document.render({ document: 'document_1', format: 'Example format' }) ``` **CLI** ```bash npx startup-builder do Document.render --json '{"document":"document_1","format":"Example format"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Document.render({ document: 'document_1', format: 'Example format' })" } } ``` ## Example The quarterly investor update is a Document in deck form. The same Document renders to PDF for email and to Markdown for an [Agent](/business/nouns/agent). # render URL: /business/nouns/document/render · Id: `verb:Document.render` · Call: `await $.Document.render({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Render produces a file from a Document in the format the reader asks for. Render produces a file from a [Document](/business/nouns/document) in the format the reader asks for. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `document` | [Document](/business/nouns/document) | Yes | The Document to render. | | `format` | `string` | Yes | The file format. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `file` | `url` | Yes | Where the file lives. | | `document` | [Document](/business/nouns/document) | Yes | The Document rendered. | ## Effects - Emits [`Document.rendered`](/business/events/Document.rendered). ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The input does not match the schema of the operation. | [`invalid-input`](/code/api/errors/invalid-input) | Read the schema of the operation, then send every required field with the right type. | [Document.render](/business/nouns/document/render) | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Document.render](/business/nouns/document/render) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Render the latest document. ``` **API** ```bash curl -X POST https://api.sb/ledgerlark.com/documents/document_1/render \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"format":"Example format"}' ``` ```json { "api": "https://api.sb/ledgerlark.com", "file": "https://ledgerlark.com", "document": { "$id": "https://api.sb/ledgerlark.com/documents/document_1", "$type": "Document", "form": "document" }, "action": { "$id": "https://api.sb/ledgerlark.com/actions/action_1", "operation": "Document.render", "status": "done" }, "links": { "self": "https://api.sb/ledgerlark.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { file, document } = await $.Document.render({ document: 'document_1', format: 'Example format' }) ``` **CLI** ```bash npx startup-builder do Document.render --json '{"document":"document_1","format":"Example format"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Document.render({ document: 'document_1', format: 'Example format' })" } } ``` # authenticate URL: /business/nouns/domain/authenticate · Id: `verb:Domain.authenticate` · Call: `await $.Domain.authenticate({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Authenticate writes a Domain’s SPF, DKIM and DMARC records and verifies them before its first send. Authenticate writes a [Domain](/business/nouns/domain)’s SPF, DKIM and DMARC records and verifies them before its first send. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `domain` | [Domain](/business/nouns/domain) | Yes | The sending Domain. | | `dmarc` | `string` | No | The DMARC policy; it starts at `none` with reports and tightens to `quarantine`. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `domain` | [Domain](/business/nouns/domain) | Yes | The Domain, authenticated. | ## Effects - Emits [`Domain.authenticated`](/business/events/Domain.authenticated). - Performed by the [Security Engineer](/agents/engineering/security-engineer). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Refuses every send from the Domain until all three records verify. - Cold outbound sends only from secondary Domains, never the Domain receipts use. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Domain.authenticate](/business/nouns/domain/authenticate) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Authenticate the latest domain. ``` **API** ```bash curl -X POST https://api.sb/routewise.dev/domains/domain_1/authenticate \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/routewise.dev", "domain": { "$id": "https://api.sb/routewise.dev/domains/domain_1", "$type": "Domain", "hostname": "routewise.dev", "role": "canonical", "state": "verifying" }, "action": { "$id": "https://api.sb/routewise.dev/actions/action_1", "operation": "Domain.authenticate", "status": "done" }, "links": { "self": "https://api.sb/routewise.dev/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const domain = await $.Domain.authenticate({ domain: 'domain_1' }) ``` **CLI** ```bash npx startup-builder do Domain.authenticate --json '{"domain":"domain_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Domain.authenticate({ domain: 'domain_1' })" } } ``` Next: [`Mailbox.create`](/business/nouns/mailbox/create) (in `guide:get-email-at-my-domain`). Guides that call it: [Get email at my domain](/products/site/domains/get-email-at-my-domain), [Send email from my domain](/start/guides/send-email-from-my-domain). # benchmark URL: /business/nouns/domain/benchmark · Id: `verb:Domain.benchmark` · Call: `await $.Domain.benchmark({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Benchmark measures a Domain’s estimated traffic, ranking Keywords, authority and referring domains beside the competitors named. Benchmark measures a [Domain](/business/nouns/domain)’s estimated traffic, ranking [Keywords](/business/nouns/keyword), authority and referring domains beside the competitors named. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `hostname` | `string` | Yes | The name to measure: the Startup’s own or a competitor’s. | | `competitors` | `string[]` | No | Names to measure beside it. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `readings` | `json` | Yes | One measure per name, each with its method and observation time. | | `domain` | [Domain](/business/nouns/domain) | Yes | The Domain measured. | ## Effects - Emits [`Domain.benchmarked`](/business/events/Domain.benchmarked). - Performed by the [Analyst](/agents/marketing/analyst). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Records each competitor as an observed relationship, never as a Domain the Startup holds. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Domain.benchmark](/business/nouns/domain/benchmark) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Benchmark the domain “taxcalc.tools”. ``` **API** ```bash curl -X POST https://api.sb/routewise.dev/domains/benchmark \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"hostname":"taxcalc.tools"}' ``` ```json { "api": "https://api.sb/routewise.dev", "readings": {}, "domain": { "$id": "https://api.sb/routewise.dev/domains/domain_1", "$type": "Domain", "hostname": "routewise.dev", "role": "canonical", "state": "verifying" }, "action": { "$id": "https://api.sb/routewise.dev/actions/action_1", "operation": "Domain.benchmark", "status": "done" }, "links": { "self": "https://api.sb/routewise.dev/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { readings, domain } = await $.Domain.benchmark({ hostname: 'taxcalc.tools' }) ``` **CLI** ```bash npx startup-builder do Domain.benchmark --json '{"hostname":"taxcalc.tools"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Domain.benchmark({ hostname: 'taxcalc.tools' })" } } ``` # claim URL: /business/nouns/domain/claim · Id: `verb:Domain.claim` · Call: `await $.Domain.claim({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Claim gives a Startup a one-label name under an issuing Domain, or assigns it a held Domain through an approved Change. Claim gives a [Startup](/business/nouns/startup) a one-label name under an issuing [Domain](/business/nouns/domain), or assigns it a held Domain through an approved [Change](/business/nouns/change). ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `hostname` | `string` | Yes | The name to claim. | | `startup` | [Startup](/business/nouns/startup) | Yes | The Startup it serves. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `domain` | [Domain](/business/nouns/domain) | Yes | The claimed Domain. | ## Effects - Emits [`Domain.claimed`](/business/events/Domain.claimed). - Performed by the [Engineering Lead](/agents/engineering/engineering-lead). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Refuses a label under an issuing Domain whose `publicSuffix` is false. - Refuses reserved labels such as `www`, `api`, `admin`, `mail`, `mcp`, `docs` and sibling Brands. - Never reissues a label released or renamed before. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Domain.claim](/business/nouns/domain/claim) | | A label under an issuing Domain whose `publicSuffix` is false | [`refused`](/code/api/errors/refused) | Clear what the check names, then call it again. | [Domain.claim](/business/nouns/domain/claim) | | Reserved labels such as `www`, `api`, `admin`, `mail`, `mcp`, `docs` and sibling Brands | [`refused`](/code/api/errors/refused) | Clear what the check names, then call it again. | [Domain.claim](/business/nouns/domain/claim) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Claim the domain “acme.headless.ly” with a startup. ``` **API** ```bash curl -X POST https://api.sb/quietcopy.com/domains/claim \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"hostname":"acme.headless.ly","startup":"startup_1"}' ``` ```json { "api": "https://api.sb/quietcopy.com", "domain": { "$id": "https://api.sb/quietcopy.com/domains/domain_1", "$type": "Domain", "hostname": "quietcopy.com", "role": "canonical", "state": "verifying" }, "action": { "$id": "https://api.sb/quietcopy.com/actions/action_1", "operation": "Domain.claim", "status": "done" }, "links": { "self": "https://api.sb/quietcopy.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const domain = await $.Domain.claim({ hostname: 'acme.headless.ly', startup: 'startup_1' }) ``` **CLI** ```bash npx startup-builder do Domain.claim --json '{"hostname":"acme.headless.ly","startup":"startup_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Domain.claim({ hostname: 'acme.headless.ly', startup: 'startup_1' })" } } ``` Next: [`Site.publish`](/business/nouns/site/publish) (in `guide:put-up-a-page`). Guides that call it: [Put up a page](/start/guides/put-up-a-page). # connect URL: /business/nouns/domain/connect · Id: `verb:Domain.connect` · Call: `await $.Domain.connect({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Connect attaches a hostname a Startup already holds and verifies ownership through DNS. Connect attaches a hostname a [Startup](/business/nouns/startup) already holds and verifies ownership through DNS. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `hostname` | `string` | Yes | The hostname to attach. | | `startup` | [Startup](/business/nouns/startup) | Yes | The Startup it serves. | | `tenant` | [Tenant](/business/nouns/tenant) | No | The Tenant it serves, when a Customer connects its own name. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `domain` | [Domain](/business/nouns/domain) | Yes | The connected Domain. | ## Effects - Emits [`Domain.connected`](/business/events/Domain.connected). - Performed by the [Integration Engineer](/agents/engineering/integration-engineer). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Issues a certificate once the DNS record verifies. - Asks for a TXT ownership proof and a CNAME that delegates certificate validation; refuses to reach `live` without the CNAME. - Refuses a wildcard name for a Tenant, and past the Tenant’s name count follows its Entitlement’s `atBound`. - Registers the Domain with Stripe as a payment method domain on the Startup’s account. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The input does not match the schema of the operation. | [`invalid-input`](/code/api/errors/invalid-input) | Read the schema of the operation, then send every required field with the right type. | [Domain.connect](/business/nouns/domain/connect) | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Domain.connect](/business/nouns/domain/connect) | | The record changed since it was read, so the write would overwrite a newer version. | [`conflict`](/code/api/errors/conflict) | Read the record again, then retry the write against its current state. | [Domain.connect](/business/nouns/domain/connect) | | A wildcard name for a Tenant, and past the Tenant’s name count follows its Entitlement’s `atBound` | [`refused`](/code/api/errors/refused) | Clear what the check names, then call it again. | [Domain.connect](/business/nouns/domain/connect) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Medium: two-way, visible | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | 1 business hour, in which a watcher can pause, redirect or cancel it; then it runs. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Connect the domain “kilnbakery.com” with a startup. ``` **API** ```bash curl -X POST https://api.sb/kilnbakery.com/domains/connect \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"hostname":"kilnbakery.com","startup":"startup_1"}' ``` ```json { "api": "https://api.sb/kilnbakery.com", "domain": { "$id": "https://api.sb/kilnbakery.com/domains/domain_1", "$type": "Domain", "hostname": "kilnbakery.com", "role": "canonical", "state": "verifying" }, "action": { "$id": "https://api.sb/kilnbakery.com/actions/action_1", "operation": "Domain.connect", "status": "done" }, "links": { "self": "https://api.sb/kilnbakery.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const domain = await $.Domain.connect({ hostname: 'kilnbakery.com', startup: 'startup_1' }) ``` **CLI** ```bash npx startup-builder do Domain.connect --json '{"hostname":"kilnbakery.com","startup":"startup_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Domain.connect({ hostname: 'kilnbakery.com', startup: 'startup_1' })" } } ``` Guides that call it: [Buy a domain](/products/site/domains/buy-a-domain), [Connect my domain](/products/site/domains/connect-my-domain). # Domain URL: /business/nouns/domain · Id: `noun:domain` > A Domain is a hostname that points at a Thing, with a role, a status, and a lifecycle tracked as data. A Domain is a hostname that points at a [Thing](/business/nouns/thing), with a role, a status, and a lifecycle tracked as data. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `hostname` | `string` | Yes | The name, such as `example.com`. | | `role` | `string` | Yes | What the Domain does for the Thing it serves; a defensive name takes `redirect`. | | `acquired` | `string` | No | One of `claimed`, `purchased`, or `connected`. | | `state` | `string` | Yes | Where the Domain stands; `verifying`, `live`, `degraded`, `expiring` and `lapsed` are observed, the rest follow an Action. | | `registrant` | [Party](/business/nouns/party) | No | The owner of record: the holding Company while held, or the holder of a self-serve Startup’s Stripe account. | | `expiresAt` | `datetime` | No | When the registration ends, as the registrar reports it; empty for a claimed Domain. | | `autoRenew` | `boolean` | No | True when renewal runs without a Decision; false sends the Domain through renewal review. | | `renewalPrice` | `money` | No | What the next renewal costs, which for a premium name differs from the purchase price. Never randomized. | | `transferableAt` | `datetime` | No | The first moment the registrar allows a transfer out, after any registration, transfer or registrant lock. | | `names` | `string` | No | How its subdomains are given out: explicit records only, or one-label claims by other Startups. | | `publicSuffix` | `boolean` | No | True once the public suffix list browsers ship carries the Domain; an issuing Domain gives out no label before then. | | `registrarAccount` | `string` | No | The registrar account that holds the Domain: one per Startup, never shared with a sibling. | | `registryLock` | `boolean` | No | True when the registry refuses transfer, update and delete until a verified out-of-band request lifts it. | | `certificate` | `json` | No | Certificate state (`pending`, `active`, `renewing` or `failed`), its expiry, and the failing check with its fix. | | `validation` | `string` | No | `delegated` proves control through a CNAME to the platform; `serving` is for an apex that cannot hold one. | | `walletsEnabled` | `boolean` | No | True once Stripe lists the Domain as a payment method domain on the Startup’s account. | | `carriedIdentity` | `boolean` | No | True once the Domain received mail, hosted a Mailbox or verified an outside account; it never resets. | | `to` | [Domain](/business/nouns/domain) | No | For a redirect: the canonical Domain it forwards to permanently, path and query kept. | ## Object ```json { "$id": "https://api.sb/kilnbakery.com/domains/domain_1", "$type": "Domain", "hostname": "kilnbakery.com", "role": "canonical", "acquired": "claimed", "state": "verifying", "registrant": "party_1", "expiresAt": "2026-10-22T12:00:00Z", "autoRenew": true, "renewalPrice": { "amount": 9, "currency": "USD" }, "transferableAt": "2026-10-22T12:00:00Z", "names": "closed", "publicSuffix": true, "registrarAccount": "registrar_account_1", "registryLock": true, "certificate": {}, "validation": "delegated", "walletsEnabled": true, "carriedIdentity": true, "to": "domain_1" } ``` ## Relationships - A Domain **hosts** one [Site](/business/nouns/site): a [Site](/business/nouns/site) answers on one or more Domains; each Domain serves one Site. `hosts`, inverse [`hostedAt`](/business/nouns/site#rel-hosted-at). - A Domain **mounts** many [Interfaces](/business/nouns/interface): an [Interface](/business/nouns/interface) answers requests on the hostnames it is mounted on. `mounts`, inverse [`mountedOn`](/business/nouns/interface#rel-mounted-on). - A Domain **records** many [DNS Records](/business/nouns/dns-record): a Domain answers DNS from its records; each record belongs to one Domain. `records`, inverse [`answersFor`](/business/nouns/dns-record#rel-answers-for). - A Domain **is registered to** one [Startup](/business/nouns/startup): a [Startup](/business/nouns/startup) holds each Domain registration and pays for the hostname. `registeredTo`, inverse [`domains`](/business/nouns/startup#rel-domains). - A Domain **serves** one [Tenant](/business/nouns/tenant): a [Tenant](/business/nouns/tenant) answers on the names its [Customer](/business/nouns/customer) connects; each such Domain serves one Tenant. `serves`, inverse [`hostnames`](/business/nouns/tenant#rel-hostnames). - A Domain **is verified by** one [Tenant](/business/nouns/tenant): a [Tenant](/business/nouns/tenant) proves control of its [Customer](/business/nouns/customer)’s email domain, so sign-ins on that domain follow the Tenant’s policy. `verifiedBy`, inverse [`verifies`](/business/nouns/tenant#rel-verifies). ## Lifecycle | State | Meaning | Moves to | | --- | --- | --- | | `candidate` (first) | A name found by search that no one here holds yet. | `held` by [Domain.register](/business/nouns/domain/register); `registered` by [Domain.register](/business/nouns/domain/register); `claimed` by [Domain.claim](/business/nouns/domain/claim); `connected` by [Domain.connect](/business/nouns/domain/connect) | | `held` | Registered to the holding Company and not yet assigned to a Startup. | `claimed` by [Domain.claim](/business/nouns/domain/claim); `released` by [Domain.release](/business/nouns/domain/release) | | `claimed` | Assigned to a Startup: a label under an issuing Domain, or a held Domain. | `live` by [Domain.verify](/business/nouns/domain/verify); `released` by [Domain.release](/business/nouns/domain/release) | | `registered` | Registered to its owner of record and pointed at the Startup’s address. | `verifying` by [Domain.verify](/business/nouns/domain/verify) | | `connected` | Attached from another registrar while its ownership proof is checked. | `verifying` by [Domain.verify](/business/nouns/domain/verify) | | `verifying` | Its first DNS, ownership and certificate checks are running. | `live` by [Domain.verify](/business/nouns/domain/verify); `degraded` by [Domain.verify](/business/nouns/domain/verify) | | `live` | Serving, with its DNS, ownership and certificate checks passing. | `degraded` by [Domain.verify](/business/nouns/domain/verify); `expiring` on [`Domain.renewalDue`](/business/nouns/domain#domainrenewaldue); `renewed` by [Domain.renew](/business/nouns/domain/renew); `transferred` by [Domain.transfer](/business/nouns/domain/transfer); `released` by [Domain.release](/business/nouns/domain/release) | | `degraded` | A check failed; a degraded canonical Domain opens an Incident. | `live` by [Domain.verify](/business/nouns/domain/verify); `released` by [Domain.release](/business/nouns/domain/release) | | `expiring` | Inside its renewal window with no renewal yet. | `renewed` by [Domain.renew](/business/nouns/domain/renew); `lapsed` on [`Domain.expired`](/business/nouns/domain#domainexpired) | | `lapsed` | Its registration ended unrenewed, and the registrar may still restore it. | `renewed` by [Domain.renew](/business/nouns/domain/renew); `released` by [Domain.release](/business/nouns/domain/release) | | `renewed` | Extended by whole years at its renewal price. | `live` by [Domain.verify](/business/nouns/domain/verify) | | `transferred` | Moved to another holder or registrar, with its record and history kept. | None: it ends here. | | `released` | Its registration or claim ended, and its record, history and aliases are kept. | None: it ends here. | ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Domain.authenticate](/business/nouns/domain/authenticate) | Authenticate writes a Domain’s SPF, DKIM and DMARC records and verifies them before its first send. | [Security Engineer](/agents/engineering/security-engineer) | [`Domain.authenticated`](/business/events/Domain.authenticated) | Two-way: `try`, `send`, `do` | | [Domain.benchmark](/business/nouns/domain/benchmark) | Benchmark measures a Domain’s estimated traffic, ranking Keywords, authority and referring domains beside the competitors named. | [Analyst](/agents/marketing/analyst) | [`Domain.benchmarked`](/business/events/Domain.benchmarked) | Two-way: `try`, `send`, `do` | | [Domain.claim](/business/nouns/domain/claim) | Claim gives a Startup a one-label name under an issuing Domain, or assigns it a held Domain through an approved Change. | [Engineering Lead](/agents/engineering/engineering-lead) | [`Domain.claimed`](/business/events/Domain.claimed) | Two-way: `try`, `send`, `do` | | [Domain.connect](/business/nouns/domain/connect) | Connect attaches a hostname a Startup already holds and verifies ownership through DNS. | [Integration Engineer](/agents/engineering/integration-engineer) | [`Domain.connected`](/business/events/Domain.connected) | Two-way: `try`, `send`, `do` | | [Domain.register](/business/nouns/domain/register) | Register buys a hostname for a Startup and points it at the Startup’s address. | [Integration Engineer](/agents/engineering/integration-engineer) | [`Domain.registered`](/business/events/Domain.registered) | One-way (money): `send`, `do` | | [Domain.release](/business/nouns/domain/release) | Release lets a Domain’s registration or claim end, keeping its record, history and aliases. | [Legal Lead](/agents/legal/legal-lead) | [`Domain.released`](/business/events/Domain.released) | One-way (customer, brand): `send`, `do` | | [Domain.renew](/business/nouns/domain/renew) | Renew extends a Domain’s registration by whole years at its renewal price, paid by its owner of record. | [Treasurer](/agents/finance/treasurer) | [`Domain.renewed`](/business/events/Domain.renewed) | One-way (money): `send`, `do` | | [Domain.search](/business/nouns/domain/search) | Search lists candidate names with availability, first-year price, renewal price and the rules of each extension. | [Engineering Lead](/agents/engineering/engineering-lead) | [`Domain.searched`](/business/events/Domain.searched) | Two-way: `try`, `send`, `do` | | [Domain.transfer](/business/nouns/domain/transfer) | Transfer moves a Domain’s registration to another holder or registrar, with its records intact. | [Legal Lead](/agents/legal/legal-lead) | [`Domain.transferred`](/business/events/Domain.transferred) | One-way (customer): `send`, `do` | | [Domain.verify](/business/nouns/domain/verify) | Verify checks a Domain’s DNS, ownership and certificate again and records each result, with the fix for any failure. | [Reliability Engineer](/agents/engineering/reliability-engineer) | [`Domain.verified`](/business/events/Domain.verified) | Two-way: `try`, `send`, `do` | | [Domain.create](/business/nouns/domain/create) | Creates a Domain. Inherited from [Noun](/business/nouns/noun). | None. | `Domain.created` | Two-way: `try`, `send`, `do` | | [Domain.get](/business/nouns/domain/get) | Returns one Domain by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Domain.list](/business/nouns/domain/list) | Returns Domains, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Domain.update](/business/nouns/domain/update) | Changes the given properties of a Domain. Inherited from [Noun](/business/nouns/noun). | None. | `Domain.updated` | Two-way: `try`, `send`, `do` | | [Domain.delete](/business/nouns/domain/delete) | Deletes a Domain; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Domain.deleted` | One-way: `send`, `do` | ## Events Events no Verb emits. Each Verb’s Event is in the Verbs table above; every Event is delivered in the same shape. ### Domain.expired A Domain’s registration passed `expiresAt` unrenewed; the registrar may still restore it. Raised by a clock. | Field | Type | Required | Description | | --- | --- | --- | --- | | `name` | `string` | Yes | `Domain.expired`. | | `at` | `datetime` | Yes | When it happened. | | `seq` | `integer` | No | Its position in the namespace, one more than the Event before; any seq is a cursor into the history. | | `data` | `json` | Yes | The Thing as the Action left it. | | `data.domain` | [Domain](/business/nouns/domain) | Yes | The Domain as the change left it. | | `data.domain.hostname` | `string` | Yes | The name, such as `example.com`. | | `data.domain.role` | `string` | Yes | What the Domain does for the Thing it serves; a defensive name takes `redirect`. | | `data.domain.acquired` | `string` | No | One of `claimed`, `purchased`, or `connected`. | | `data.domain.state` | `string` | Yes | Where the Domain stands; `verifying`, `live`, `degraded`, `expiring` and `lapsed` are observed, the rest follow an Action. | | `data.domain.registrant` | [Party](/business/nouns/party) | No | The owner of record: the holding Company while held, or the holder of a self-serve Startup’s Stripe account. | | `data.domain.expiresAt` | `datetime` | No | When the registration ends, as the registrar reports it; empty for a claimed Domain. | | `data.domain.autoRenew` | `boolean` | No | True when renewal runs without a Decision; false sends the Domain through renewal review. | | `data.domain.renewalPrice` | `money` | No | What the next renewal costs, which for a premium name differs from the purchase price. | | `data.domain.transferableAt` | `datetime` | No | The first moment the registrar allows a transfer out, after any registration, transfer or registrant lock. | | `data.domain.names` | `string` | No | How its subdomains are given out: explicit records only, or one-label claims by other Startups. | | `data.domain.publicSuffix` | `boolean` | No | True once the public suffix list browsers ship carries the Domain; an issuing Domain gives out no label before then. | | `data.domain.registrarAccount` | `string` | No | The registrar account that holds the Domain: one per Startup, never shared with a sibling. | | `data.domain.registryLock` | `boolean` | No | True when the registry refuses transfer, update and delete until a verified out-of-band request lifts it. | | `data.domain.certificate` | `json` | No | Certificate state (`pending`, `active`, `renewing` or `failed`), its expiry, and the failing check with its fix. | | `data.domain.validation` | `string` | No | `delegated` proves control through a CNAME to the platform; `serving` is for an apex that cannot hold one. | | `data.domain.walletsEnabled` | `boolean` | No | True once Stripe lists the Domain as a payment method domain on the Startup’s account. | | `data.domain.carriedIdentity` | `boolean` | No | True once the Domain received mail, hosted a Mailbox or verified an outside account; it never resets. | | `data.domain.to` | [Domain](/business/nouns/domain) | No | For a redirect: the canonical Domain it forwards to permanently, path and query kept. | | `data.previous.state` | `string` | Yes | The `state` before this Event: `expiring`. | ```json { "$id": "https://api.sb/kilnbakery.com/events/event_1", "$type": "Event", "name": "Domain.expired", "at": "2026-10-22T12:00:00Z", "data": { "domain": { "$id": "https://api.sb/kilnbakery.com/domains/domain_1", "$type": "Domain", "hostname": "kilnbakery.com", "role": "canonical", "acquired": "claimed", "state": "lapsed", "registrant": "party_1", "expiresAt": "2026-10-22T12:00:00Z", "autoRenew": true, "renewalPrice": { "amount": 9, "currency": "USD" }, "transferableAt": "2026-10-22T12:00:00Z", "names": "closed", "publicSuffix": true, "registrarAccount": "registrar_account_1", "registryLock": true, "certificate": {}, "validation": "delegated", "walletsEnabled": true, "carriedIdentity": true, "to": "domain_1" }, "previous": { "state": "expiring" } }, "seq": 1 } ``` ### Domain.renewalDue A live Domain entered its renewal window with no renewal yet. Raised by a clock. | Field | Type | Required | Description | | --- | --- | --- | --- | | `name` | `string` | Yes | `Domain.renewalDue`. | | `at` | `datetime` | Yes | When it happened. | | `seq` | `integer` | No | Its position in the namespace, one more than the Event before; any seq is a cursor into the history. | | `data` | `json` | Yes | The Thing as the Action left it. | | `data.domain` | [Domain](/business/nouns/domain) | Yes | The Domain as the change left it. | | `data.domain.hostname` | `string` | Yes | The name, such as `example.com`. | | `data.domain.role` | `string` | Yes | What the Domain does for the Thing it serves; a defensive name takes `redirect`. | | `data.domain.acquired` | `string` | No | One of `claimed`, `purchased`, or `connected`. | | `data.domain.state` | `string` | Yes | Where the Domain stands; `verifying`, `live`, `degraded`, `expiring` and `lapsed` are observed, the rest follow an Action. | | `data.domain.registrant` | [Party](/business/nouns/party) | No | The owner of record: the holding Company while held, or the holder of a self-serve Startup’s Stripe account. | | `data.domain.expiresAt` | `datetime` | No | When the registration ends, as the registrar reports it; empty for a claimed Domain. | | `data.domain.autoRenew` | `boolean` | No | True when renewal runs without a Decision; false sends the Domain through renewal review. | | `data.domain.renewalPrice` | `money` | No | What the next renewal costs, which for a premium name differs from the purchase price. | | `data.domain.transferableAt` | `datetime` | No | The first moment the registrar allows a transfer out, after any registration, transfer or registrant lock. | | `data.domain.names` | `string` | No | How its subdomains are given out: explicit records only, or one-label claims by other Startups. | | `data.domain.publicSuffix` | `boolean` | No | True once the public suffix list browsers ship carries the Domain; an issuing Domain gives out no label before then. | | `data.domain.registrarAccount` | `string` | No | The registrar account that holds the Domain: one per Startup, never shared with a sibling. | | `data.domain.registryLock` | `boolean` | No | True when the registry refuses transfer, update and delete until a verified out-of-band request lifts it. | | `data.domain.certificate` | `json` | No | Certificate state (`pending`, `active`, `renewing` or `failed`), its expiry, and the failing check with its fix. | | `data.domain.validation` | `string` | No | `delegated` proves control through a CNAME to the platform; `serving` is for an apex that cannot hold one. | | `data.domain.walletsEnabled` | `boolean` | No | True once Stripe lists the Domain as a payment method domain on the Startup’s account. | | `data.domain.carriedIdentity` | `boolean` | No | True once the Domain received mail, hosted a Mailbox or verified an outside account; it never resets. | | `data.domain.to` | [Domain](/business/nouns/domain) | No | For a redirect: the canonical Domain it forwards to permanently, path and query kept. | | `data.daysLeft` | `integer` | Yes | Days until `expiresAt`. | | `data.previous.state` | `string` | Yes | The `state` before this Event: `live`. | ```json { "$id": "https://api.sb/kilnbakery.com/events/event_1", "$type": "Event", "name": "Domain.renewalDue", "at": "2026-10-22T12:00:00Z", "data": { "domain": { "$id": "https://api.sb/kilnbakery.com/domains/domain_1", "$type": "Domain", "hostname": "kilnbakery.com", "role": "canonical", "acquired": "claimed", "state": "expiring", "registrant": "party_1", "expiresAt": "2026-10-22T12:00:00Z", "autoRenew": true, "renewalPrice": { "amount": 9, "currency": "USD" }, "transferableAt": "2026-10-22T12:00:00Z", "names": "closed", "publicSuffix": true, "registrarAccount": "registrar_account_1", "registryLock": true, "certificate": {}, "validation": "delegated", "walletsEnabled": true, "carriedIdentity": true, "to": "domain_1" }, "daysLeft": 30, "previous": { "state": "live" } }, "seq": 1 } ``` ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Domain.create` | Yes | Yes | Yes | No | | `Domain.get` | Yes | Yes | Yes | Yes | | `Domain.list` | Yes | Yes | Yes | Yes | | `Domain.update` | Yes | Yes | Yes | No | | `Domain.delete` | Yes | Yes | Yes | No | | `Domain.authenticate` | Yes | Yes | Yes | No | | `Domain.benchmark` | Yes | Yes | Yes | No | | `Domain.claim` | Yes | Yes | Yes | No | | `Domain.connect` | Yes | Yes | Yes | No | | `Domain.register` | Yes | No | No | No | | `Domain.release` | Yes | No | No | No | | `Domain.renew` | Yes | No | No | No | | `Domain.search` | Yes | Yes | Yes | No | | `Domain.transfer` | Yes | No | No | No | | `Domain.verify` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Register the domain “patentpad.com” with a startup. ``` **API** ```bash curl -X POST https://api.sb/patentpad.com/domains/register \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"hostname":"patentpad.com","startup":"startup_1"}' ``` ```json { "api": "https://api.sb/patentpad.com", "domain": { "$id": "https://api.sb/patentpad.com/domains/domain_1", "$type": "Domain", "hostname": "patentpad.com", "role": "canonical", "state": "verifying" }, "action": { "$id": "https://api.sb/patentpad.com/actions/action_1", "operation": "Domain.register", "status": "done" }, "links": { "self": "https://api.sb/patentpad.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const domain = await $.Domain.register({ hostname: 'patentpad.com', startup: 'startup_1' }) ``` **CLI** ```bash npx startup-builder do Domain.register --json '{"hostname":"patentpad.com","startup":"startup_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Domain.register({ hostname: 'patentpad.com', startup: 'startup_1' })" } } ``` ## Example ```text hostname role state to permitly.dev canonical live the Site, /docs, /portal, /api and /mcp api.permitly.dev alias live the same API as /api permitly.com redirect live permitly.dev ``` # register URL: /business/nouns/domain/register · Id: `verb:Domain.register` · Call: `await $.Domain.register({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Register buys a hostname for a Startup and points it at the Startup’s address. Register buys a hostname for a [Startup](/business/nouns/startup) and points it at the Startup’s address. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `hostname` | `string` | Yes | The hostname to buy. | | `startup` | [Startup](/business/nouns/startup) | Yes | The Startup it serves. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `domain` | [Domain](/business/nouns/domain) | Yes | The registered Domain. | ## Effects - Emits [`Domain.registered`](/business/events/Domain.registered). - Performed by the [Integration Engineer](/agents/engineering/integration-engineer). - One-way (money): it waits out its delay window, and runs in the `send` and `do` modes. - Renews the registration before it expires, as spend under the Startup’s Limits. - Checks the spend Limit; above it, opens an Approval. - Refuses on a provisional self-serve Startup; the name stays a candidate until `Startup.claim`. - Registers the name to the owner of record, in the Startup’s own registrar account, with DNSSEC and a CAA record. - Writes null SPF, DMARC reject and null MX records unless the Domain hosts a Mailbox. - Registers the Domain with Stripe as a payment method domain on the Startup’s account. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The operation is part of an Offer the caller has not accepted or paid for. | [`payment-required`](/code/api/errors/payment-required) | Accept the Offer named in the response, then retry the call. | [Offer.accept](/business/nouns/offer/accept) | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Domain.register](/business/nouns/domain/register) | | The record changed since it was read, so the write would overwrite a newer version. | [`conflict`](/code/api/errors/conflict) | Read the record again, then retry the write against its current state. | [Domain.register](/business/nouns/domain/register) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Medium: one-way, bounded (money) | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | 1 business hour, in which a watcher can pause, redirect or cancel it; then it runs. | | Limit | The spend [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) or [Mandate](/business/nouns/mandate) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Register the domain “patentpad.com” with a startup. ``` **API** ```bash curl -X POST https://api.sb/patentpad.com/domains/register \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"hostname":"patentpad.com","startup":"startup_1"}' ``` ```json { "api": "https://api.sb/patentpad.com", "domain": { "$id": "https://api.sb/patentpad.com/domains/domain_1", "$type": "Domain", "hostname": "patentpad.com", "role": "canonical", "state": "verifying" }, "action": { "$id": "https://api.sb/patentpad.com/actions/action_1", "operation": "Domain.register", "status": "done" }, "links": { "self": "https://api.sb/patentpad.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const domain = await $.Domain.register({ hostname: 'patentpad.com', startup: 'startup_1' }) ``` **CLI** ```bash npx startup-builder do Domain.register --json '{"hostname":"patentpad.com","startup":"startup_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Domain.register({ hostname: 'patentpad.com', startup: 'startup_1' })" } } ``` Next: [`Domain.connect`](/business/nouns/domain/connect) (in `guide:buy-a-domain`). Guides that call it: [Buy a domain](/products/site/domains/buy-a-domain). # release URL: /business/nouns/domain/release · Id: `verb:Domain.release` · Call: `await $.Domain.release({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Release lets a Domain’s registration or claim end, keeping its record, history and aliases. Release lets a [Domain](/business/nouns/domain)’s registration or claim end, keeping its record, history and aliases. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `domain` | [Domain](/business/nouns/domain) | Yes | The Domain to let go. | | `reason` | `text` | Yes | Why it is released, recorded as a Decision. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `domain` | [Domain](/business/nouns/domain) | Yes | The released Domain. | ## Effects - Emits [`Domain.released`](/business/events/Domain.released). - Performed by the [Legal Lead](/agents/legal/legal-lead). - One-way (customer, brand): it waits out its delay window, and runs in the `send` and `do` modes. - Refuses a Domain whose `carriedIdentity` is true: it received mail, hosted a Mailbox or verified an outside account. - Refuses a canonical Domain while the Startup is Live. - Runs when a Tenant ends or loses its Entitlement, for each name that Tenant connected. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Domain.release](/business/nouns/domain/release) | | A Domain whose `carriedIdentity` is true: it received mail, hosted a Mailbox or verified an outside account | [`refused`](/code/api/errors/refused) | Clear what the check names, then call it again. | [Domain.release](/business/nouns/domain/release) | | A canonical Domain while the Startup is Live | [`refused`](/code/api/errors/refused) | Clear what the check names, then call it again. | [Domain.release](/business/nouns/domain/release) | ## When it waits | Gate | Default | | --- | --- | | Decision class | High: one-way, broad (customer, brand) | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | 1 business day, in which a watcher can pause, redirect or cancel it; then it runs. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Release the latest domain. ``` **API** ```bash curl -X POST https://api.sb/shiftnote.app/domains/domain_1/release \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"reason":"Example reason"}' ``` ```json { "api": "https://api.sb/shiftnote.app", "domain": { "$id": "https://api.sb/shiftnote.app/domains/domain_1", "$type": "Domain", "hostname": "shiftnote.app", "role": "canonical", "state": "verifying" }, "action": { "$id": "https://api.sb/shiftnote.app/actions/action_1", "operation": "Domain.release", "status": "done" }, "links": { "self": "https://api.sb/shiftnote.app/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const domain = await $.Domain.release({ domain: 'domain_1', reason: 'Example reason' }) ``` **CLI** ```bash npx startup-builder do Domain.release --json '{"domain":"domain_1","reason":"Example reason"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Domain.release({ domain: 'domain_1', reason: 'Example reason' })" } } ``` # renew URL: /business/nouns/domain/renew · Id: `verb:Domain.renew` · Call: `await $.Domain.renew({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Renew extends a Domain’s registration by whole years at its renewal price, paid by its owner of record. Renew extends a [Domain](/business/nouns/domain)’s registration by whole years at its renewal price, paid by its owner of record. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `domain` | [Domain](/business/nouns/domain) | Yes | The Domain to renew. | | `years` | `integer` | No | Years to add. Defaults to the Domain’s tier in the renewal Setting. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `domain` | [Domain](/business/nouns/domain) | Yes | The Domain, with its new `expiresAt`. | ## Effects - Emits [`Domain.renewed`](/business/events/Domain.renewed). - Performed by the [Treasurer](/agents/finance/treasurer). - One-way (money): it waits out its delay window, and runs in the `send` and `do` modes. - Runs inside the tier’s renewal window: 90 days for a canonical Domain, 60 for others. - Keeps renewing while the Startup is Dormant, because Domain renewal never stops. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Domain.renew](/business/nouns/domain/renew) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Medium: one-way, bounded (money) | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | 1 business hour, in which a watcher can pause, redirect or cancel it; then it runs. | | Limit | The spend [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) or [Mandate](/business/nouns/mandate) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Renew the latest domain. ``` **API** ```bash curl -X POST https://api.sb/shiftnote.app/domains/domain_1/renew \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/shiftnote.app", "domain": { "$id": "https://api.sb/shiftnote.app/domains/domain_1", "$type": "Domain", "hostname": "shiftnote.app", "role": "canonical", "state": "verifying" }, "action": { "$id": "https://api.sb/shiftnote.app/actions/action_1", "operation": "Domain.renew", "status": "done" }, "links": { "self": "https://api.sb/shiftnote.app/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const domain = await $.Domain.renew({ domain: 'domain_1' }) ``` **CLI** ```bash npx startup-builder do Domain.renew --json '{"domain":"domain_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Domain.renew({ domain: 'domain_1' })" } } ``` # search URL: /business/nouns/domain/search · Id: `verb:Domain.search` · Call: `await $.Domain.search({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Search lists candidate names with availability, first-year price, renewal price and the rules of each extension. Search lists candidate names with availability, first-year price, renewal price and the rules of each extension. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `query` | `string` | Yes | A name, or a word to build names from. | | `extensions` | `string[]` | No | Extensions to check, such as `com` or `ai`. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `candidates` | list of [Domain](/business/nouns/domain) | Yes | Candidate Domains, each with its prices, three-year cost and extension rules. | ## Effects - Emits [`Domain.searched`](/business/events/Domain.searched). - Performed by the [Engineering Lead](/agents/engineering/engineering-lead). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Drops a candidate whose extension rules the owner of record fails, such as a local-presence rule. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Domain.search](/business/nouns/domain/search) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Search the latest domain. ``` **API** ```bash curl -X POST https://api.sb/kilnbakery.com/domains/search \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"query":"Example query"}' ``` ```json { "api": "https://api.sb/kilnbakery.com", "candidates": [ { "$id": "https://api.sb/kilnbakery.com/domains/domain_1", "$type": "Domain", "hostname": "kilnbakery.com", "role": "canonical", "state": "verifying" } ], "action": { "$id": "https://api.sb/kilnbakery.com/actions/action_1", "operation": "Domain.search", "status": "done" }, "links": { "self": "https://api.sb/kilnbakery.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const candidates = await $.Domain.search({ query: 'Example query' }) ``` **CLI** ```bash npx startup-builder do Domain.search --json '{"query":"Example query"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Domain.search({ query: 'Example query' })" } } ``` Next: [`Domain.register`](/business/nouns/domain/register) (in `guide:buy-a-domain`). Guides that call it: [Buy a domain](/products/site/domains/buy-a-domain). # transfer URL: /business/nouns/domain/transfer · Id: `verb:Domain.transfer` · Call: `await $.Domain.transfer({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Transfer moves a Domain’s registration to another holder or registrar, with its records intact. Transfer moves a [Domain](/business/nouns/domain)’s registration to another holder or registrar, with its records intact. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `domain` | [Domain](/business/nouns/domain) | Yes | The Domain to move. | | `to` | `string` | Yes | The receiving holder or registrar. | | `kind` | `string` | Yes | `in` from another registrar, `registrant` to a new owner, `push` between accounts, or `out` to leave. | | `code` | [Secret](/business/nouns/secret) | No | The transfer code, for `in` and `out`. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `domain` | [Domain](/business/nouns/domain) | Yes | The transferred Domain. | ## Effects - Emits [`Domain.transferred`](/business/events/Domain.transferred). - Performed by the [Legal Lead](/agents/legal/legal-lead). - One-way (customer): it waits out its delay window, and runs in the `send` and `do` modes. - Refuses before `transferableAt`. - Keeps the record and its history; a claimed label moves as a redirect, then retires. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Domain.transfer](/business/nouns/domain/transfer) | | The record is not in a state that allows this Verb, so the call is refused. | [`refused`](/code/api/errors/refused) | Read the record, run the Verb that moves it to an allowed state, then retry. | [Domain.transfer](/business/nouns/domain/transfer) | | Before `transferableAt` | [`refused`](/code/api/errors/refused) | Clear what the check names, then call it again. | [Domain.transfer](/business/nouns/domain/transfer) | ## When it waits | Gate | Default | | --- | --- | | Decision class | High: one-way, broad (customer) | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | 1 business day, in which a watcher can pause, redirect or cancel it; then it runs. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Transfer the latest domain. ``` **API** ```bash curl -X POST https://api.sb/shiftnote.app/domains/domain_1/transfer \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"to":"Example to","kind":"in"}' ``` ```json { "api": "https://api.sb/shiftnote.app", "domain": { "$id": "https://api.sb/shiftnote.app/domains/domain_1", "$type": "Domain", "hostname": "shiftnote.app", "role": "canonical", "state": "verifying" }, "action": { "$id": "https://api.sb/shiftnote.app/actions/action_1", "operation": "Domain.transfer", "status": "done" }, "links": { "self": "https://api.sb/shiftnote.app/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const domain = await $.Domain.transfer({ domain: 'domain_1', to: 'Example to', kind: 'in' }) ``` **CLI** ```bash npx startup-builder do Domain.transfer --json '{"domain":"domain_1","to":"Example to","kind":"in"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Domain.transfer({ domain: 'domain_1', to: 'Example to', kind: 'in' })" } } ``` # verify URL: /business/nouns/domain/verify · Id: `verb:Domain.verify` · Call: `await $.Domain.verify({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Verify checks a Domain’s DNS, ownership and certificate again and records each result, with the fix for any failure. Verify checks a [Domain](/business/nouns/domain)’s DNS, ownership and certificate again and records each result, with the fix for any failure. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `domain` | [Domain](/business/nouns/domain) | Yes | The Domain to check. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `checks` | `json` | Yes | Each check with its status and, on failure, its reason and fix. | | `domain` | [Domain](/business/nouns/domain) | Yes | The Domain with its `state` after the checks. | ## Effects - Emits [`Domain.verified`](/business/events/Domain.verified). - Performed by the [Reliability Engineer](/agents/engineering/reliability-engineer). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Moves a live Domain to `degraded` when a check fails; a degraded canonical Domain opens an Incident. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Domain.verify](/business/nouns/domain/verify) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Verify the latest domain. ``` **API** ```bash curl -X POST https://api.sb/routewise.dev/domains/domain_1/verify \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/routewise.dev", "checks": {}, "domain": { "$id": "https://api.sb/routewise.dev/domains/domain_1", "$type": "Domain", "hostname": "routewise.dev", "role": "canonical", "state": "verifying" }, "action": { "$id": "https://api.sb/routewise.dev/actions/action_1", "operation": "Domain.verify", "status": "done" }, "links": { "self": "https://api.sb/routewise.dev/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { checks, domain } = await $.Domain.verify({ domain: 'domain_1' }) ``` **CLI** ```bash npx startup-builder do Domain.verify --json '{"domain":"domain_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Domain.verify({ domain: 'domain_1' })" } } ``` Guides that call it: [Fix my domain](/products/site/domains/fix-my-domain). # cancel URL: /business/nouns/enrollment/cancel · Id: `verb:Enrollment.cancel` · Call: `await $.Enrollment.cancel({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Cancel ends one Contact’s run through a Sequence for good, with the reason it records as `exitReason`. Cancel ends one [Contact](/business/nouns/contact)’s run through a [Sequence](/business/nouns/sequence) for good, with the reason it records as `exitReason`. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `enrollment` | [Enrollment](/business/nouns/enrollment) | Yes | The Enrollment to end. | | `reason` | `string` | Yes | Why it ends. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `enrollment` | [Enrollment](/business/nouns/enrollment) | Yes | The Enrollment, now `exited`. | ## Effects - Emits [`Enrollment.canceled`](/business/events/Enrollment.canceled). - Performed by the [Prospector](/agents/sales/prospector). - Two-way: it runs at once, in the `try`, `send` and `do` modes. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Enrollment.cancel](/business/nouns/enrollment/cancel) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Cancel the latest enrollment. ``` **API** ```bash curl -X POST https://api.sb/quietcopy.com/enrollments/enrollment_1/cancel \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"reason":"replied"}' ``` ```json { "api": "https://api.sb/quietcopy.com", "enrollment": { "$id": "https://api.sb/quietcopy.com/enrollments/enrollment_1", "$type": "Enrollment", "status": "active", "step": "Example step" }, "action": { "$id": "https://api.sb/quietcopy.com/actions/action_1", "operation": "Enrollment.cancel", "status": "done" }, "links": { "self": "https://api.sb/quietcopy.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const enrollment = await $.Enrollment.cancel({ enrollment: 'enrollment_1', reason: 'replied' }) ``` **CLI** ```bash npx startup-builder do Enrollment.cancel --json '{"enrollment":"enrollment_1","reason":"replied"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Enrollment.cancel({ enrollment: 'enrollment_1', reason: 'replied' })" } } ``` # Enrollment URL: /business/nouns/enrollment · Id: `noun:enrollment` > An Enrollment is one person’s run through one Sequence: the current step, when the next fires, the branches taken, and why it ended. An Enrollment is one person’s run through one [Sequence](/business/nouns/sequence): the current step, when the next fires, the branches taken, and why it ended. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `status` | `string` | Yes | Where the run stands. | | `step` | `string` | Yes | The Sequence step the person is on. | | `nextAt` | `datetime` | No | When the next step fires; empty while paused or exited. | | `branches` | `string[]` | No | The branches taken so far, in order. | | `exitReason` | `string` | No | Why the run ended. | ## Object ```json { "$id": "https://api.sb/petpantry.shop/enrollments/enrollment_1", "$type": "Enrollment", "status": "active", "step": "Example step", "nextAt": "2026-10-22T12:00:00Z", "branches": [ "Example branches" ], "exitReason": "replied" } ``` ## Relationships - An Enrollment **follows** one [Sequence](/business/nouns/sequence): the [Sequence](/business/nouns/sequence) whose steps this Enrollment walks, one step at a time. `follows`, inverse [`enrollments`](/business/nouns/sequence#rel-enrollments). - An Enrollment **runs for** one [Contact](/business/nouns/contact): the [Contact](/business/nouns/contact) this run belongs to; pausing one Contact’s nurture pauses this Enrollment. `runsFor`, inverse [`enrollments`](/business/nouns/contact#rel-enrollments). ## Lifecycle | State | Meaning | Moves to | | --- | --- | --- | | `active` (first) | The Contact is on a step, and the next one fires at `nextAt`. | `paused` by [Enrollment.pause](/business/nouns/enrollment/pause); `exited` by [Enrollment.cancel](/business/nouns/enrollment/cancel); `exited` on `Message.created` when the enrolled Contact replies; `exited` on [`Order.placed`](/business/events/Order.placed) when the buyer is the enrolled Contact; `exited` on [`Contact.unsubscribed`](/business/events/Contact.unsubscribed) when the Contact is the enrolled one; `exited` on [`Contact.suppressed`](/business/events/Contact.suppressed) when the Contact is the enrolled one; `exited` on [`Enrollment.finished`](/business/nouns/enrollment#enrollmentfinished) | | `paused` | No step fires, and `nextAt` stays empty until it resumes. | `active` by [Enrollment.resume](/business/nouns/enrollment/resume); `exited` by [Enrollment.cancel](/business/nouns/enrollment/cancel); `exited` on [`Contact.suppressed`](/business/events/Contact.suppressed) when the Contact is the enrolled one | | `exited` | Ended, with its `exitReason`; enrolling the Contact again starts a new Enrollment. | None: it ends here. | ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Enrollment.cancel](/business/nouns/enrollment/cancel) | Cancel ends one Contact’s run through a Sequence for good, with the reason it records as `exitReason`. | [Prospector](/agents/sales/prospector) | [`Enrollment.canceled`](/business/events/Enrollment.canceled) | Two-way: `try`, `send`, `do` | | [Enrollment.pause](/business/nouns/enrollment/pause) | Pause stops one Contact’s run through a Sequence at its current step, without ending it. | [Prospector](/agents/sales/prospector) | [`Enrollment.paused`](/business/events/Enrollment.paused) | Two-way: `try`, `send`, `do` | | [Enrollment.resume](/business/nouns/enrollment/resume) | Resume restarts a paused run at the step it stopped on and sets when that step fires. | [Prospector](/agents/sales/prospector) | [`Enrollment.resumed`](/business/events/Enrollment.resumed) | Two-way: `try`, `send`, `do` | | [Enrollment.create](/business/nouns/enrollment/create) | Creates an Enrollment. Inherited from [Noun](/business/nouns/noun). | None. | `Enrollment.created` | Two-way: `try`, `send`, `do` | | [Enrollment.get](/business/nouns/enrollment/get) | Returns one Enrollment by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Enrollment.list](/business/nouns/enrollment/list) | Returns Enrollments, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Enrollment.update](/business/nouns/enrollment/update) | Changes the given properties of an Enrollment. Inherited from [Noun](/business/nouns/noun). | None. | `Enrollment.updated` | Two-way: `try`, `send`, `do` | | [Enrollment.delete](/business/nouns/enrollment/delete) | Deletes an Enrollment; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Enrollment.deleted` | One-way: `send`, `do` | ## Events Events no Verb emits. Each Verb’s Event is in the Verbs table above; every Event is delivered in the same shape. ### Enrollment.finished A Contact passed the last step of a Sequence with no exit Event, so the run ends with `exitReason` `finished`. Raised by the runtime. | Field | Type | Required | Description | | --- | --- | --- | --- | | `name` | `string` | Yes | `Enrollment.finished`. | | `at` | `datetime` | Yes | When it happened. | | `seq` | `integer` | No | Its position in the namespace, one more than the Event before; any seq is a cursor into the history. | | `data` | `json` | Yes | The Thing as the Action left it. | | `data.enrollment` | [Enrollment](/business/nouns/enrollment) | Yes | The Enrollment as the change left it. | | `data.enrollment.status` | `string` | Yes | Where the run stands. | | `data.enrollment.step` | `string` | Yes | The Sequence step the person is on. | | `data.enrollment.nextAt` | `datetime` | No | When the next step fires; empty while paused or exited. | | `data.enrollment.branches` | `string[]` | No | The branches taken so far, in order. | | `data.enrollment.exitReason` | `string` | No | Why the run ended. | | `data.previous.status` | `string` | Yes | The `status` before this Event: `active`. | ```json { "$id": "https://api.sb/petpantry.shop/events/event_1", "$type": "Event", "name": "Enrollment.finished", "at": "2026-10-22T12:00:00Z", "data": { "enrollment": { "$id": "https://api.sb/petpantry.shop/enrollments/enrollment_1", "$type": "Enrollment", "status": "exited", "step": "Example step", "nextAt": "2026-10-22T12:00:00Z", "branches": [ "Example branches" ], "exitReason": "replied" }, "previous": { "status": "active" } }, "seq": 1 } ``` ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Enrollment.create` | Yes | Yes | Yes | No | | `Enrollment.get` | Yes | Yes | Yes | Yes | | `Enrollment.list` | Yes | Yes | Yes | Yes | | `Enrollment.update` | Yes | Yes | Yes | No | | `Enrollment.delete` | Yes | Yes | Yes | No | | `Enrollment.cancel` | Yes | Yes | Yes | No | | `Enrollment.pause` | Yes | Yes | Yes | No | | `Enrollment.resume` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Pause the latest enrollment. ``` **API** ```bash curl -X POST https://api.sb/kilnbakery.com/enrollments/enrollment_1/pause \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/kilnbakery.com", "enrollment": { "$id": "https://api.sb/kilnbakery.com/enrollments/enrollment_1", "$type": "Enrollment", "status": "active", "step": "Example step" }, "action": { "$id": "https://api.sb/kilnbakery.com/actions/action_1", "operation": "Enrollment.pause", "status": "done" }, "links": { "self": "https://api.sb/kilnbakery.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const enrollment = await $.Enrollment.pause({ enrollment: 'enrollment_1' }) ``` **CLI** ```bash npx startup-builder do Enrollment.pause --json '{"enrollment":"enrollment_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Enrollment.pause({ enrollment: 'enrollment_1' })" } } ``` ## Example A trial user of a budgeting app enters the onboarding [Sequence](/business/nouns/sequence). After she links a bank account the Enrollment takes the `linked` branch, and it ends with exit reason `purchased` on day 9. # pause URL: /business/nouns/enrollment/pause · Id: `verb:Enrollment.pause` · Call: `await $.Enrollment.pause({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Pause stops one Contact’s run through a Sequence at its current step, without ending it. Pause stops one person’s run through a [Sequence](/business/nouns/sequence) at the step they are on, without ending it. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `enrollment` | [Enrollment](/business/nouns/enrollment) | Yes | The Enrollment to pause. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `enrollment` | [Enrollment](/business/nouns/enrollment) | Yes | The Enrollment, now `paused`. | ## Effects - Emits [`Enrollment.paused`](/business/events/Enrollment.paused). - Performed by the [Prospector](/agents/sales/prospector). - Two-way: it runs at once, in the `try`, `send` and `do` modes. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Enrollment.pause](/business/nouns/enrollment/pause) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Pause the latest enrollment. ``` **API** ```bash curl -X POST https://api.sb/kilnbakery.com/enrollments/enrollment_1/pause \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/kilnbakery.com", "enrollment": { "$id": "https://api.sb/kilnbakery.com/enrollments/enrollment_1", "$type": "Enrollment", "status": "active", "step": "Example step" }, "action": { "$id": "https://api.sb/kilnbakery.com/actions/action_1", "operation": "Enrollment.pause", "status": "done" }, "links": { "self": "https://api.sb/kilnbakery.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const enrollment = await $.Enrollment.pause({ enrollment: 'enrollment_1' }) ``` **CLI** ```bash npx startup-builder do Enrollment.pause --json '{"enrollment":"enrollment_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Enrollment.pause({ enrollment: 'enrollment_1' })" } } ``` # resume URL: /business/nouns/enrollment/resume · Id: `verb:Enrollment.resume` · Call: `await $.Enrollment.resume({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Resume restarts a paused run at the step it stopped on and sets when that step fires. Resume restarts a paused run at the step it stopped on and sets when that step fires. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `enrollment` | [Enrollment](/business/nouns/enrollment) | Yes | The paused Enrollment. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `enrollment` | [Enrollment](/business/nouns/enrollment) | Yes | The Enrollment, `active` again. | ## Effects - Emits [`Enrollment.resumed`](/business/events/Enrollment.resumed). - Performed by the [Prospector](/agents/sales/prospector). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Sets `nextAt` from the step’s wait, counted from now. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Enrollment.resume](/business/nouns/enrollment/resume) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Resume the latest enrollment. ``` **API** ```bash curl -X POST https://api.sb/shiftnote.app/enrollments/enrollment_1/resume \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/shiftnote.app", "enrollment": { "$id": "https://api.sb/shiftnote.app/enrollments/enrollment_1", "$type": "Enrollment", "status": "active", "step": "Example step" }, "action": { "$id": "https://api.sb/shiftnote.app/actions/action_1", "operation": "Enrollment.resume", "status": "done" }, "links": { "self": "https://api.sb/shiftnote.app/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const enrollment = await $.Enrollment.resume({ enrollment: 'enrollment_1' }) ``` **CLI** ```bash npx startup-builder do Enrollment.resume --json '{"enrollment":"enrollment_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Enrollment.resume({ enrollment: 'enrollment_1' })" } } ``` # check URL: /business/nouns/entitlement/check · Id: `verb:Entitlement.check` · Call: `await $.Entitlement.check({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Check says whether a Customer may call a Verb now, how much of its Limit remains, when that resets, and which Offer lifts it. Check says whether a [Customer](/business/nouns/customer) may call a [Verb](/business/nouns/verb) now, how much of its [Limit](/business/nouns/limit) remains, when that resets, and which [Offer](/business/nouns/offer) lifts it. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `customer` | [Customer](/business/nouns/customer) | Yes | The Customer making the call. | | `verb` | [Verb](/business/nouns/verb) | Yes | The Verb it wants to call, as `Noun.verb`. | | `amount` | `integer` | No | How many units the call would use. Defaults to 1. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `allowed` | `boolean` | Yes | True when an Entitlement grants the call and its Limit has room for `amount`. | | `entitlement` | [Entitlement](/business/nouns/entitlement) | No | The Entitlement that grants the Verb, when one does. | | `remaining` | `integer` | No | Units left in the current period; absent for a `feature` Entitlement. | | `resetsAt` | `datetime` | No | When the period resets; absent when the Limit never resets. | | `upgrade` | [Offer](/business/nouns/offer) | No | The Offer that lifts the bound, when its Offer’s `atBound` is `upgrade`. | ## Effects - Emits [`Entitlement.checked`](/business/events/Entitlement.checked). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Changes nothing and never refuses: past the bound it answers `allowed: false`, and the Verb it guards then replies 402 `payment-required`, unless `atBound` is `overage`. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Entitlement.check](/business/nouns/entitlement/check) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Check the latest entitlement with a customer and a verb. ``` **API** ```bash curl -X POST https://api.sb/ledgerlark.com/entitlements/check \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"customer":"customer_1","verb":"verb_1"}' ``` ```json { "api": "https://api.sb/ledgerlark.com", "allowed": true, "entitlement": { "$id": "https://api.sb/ledgerlark.com/entitlements/entitlement_1", "$type": "Entitlement", "verb": "verb_1" }, "remaining": 1, "resetsAt": "2026-10-22T12:00:00Z", "upgrade": { "$id": "https://api.sb/ledgerlark.com/offers/offer_1", "$type": "Offer", "price": { "amount": 400, "currency": "USD" } }, "action": { "$id": "https://api.sb/ledgerlark.com/actions/action_1", "operation": "Entitlement.check", "status": "done" }, "links": { "self": "https://api.sb/ledgerlark.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { allowed, entitlement, remaining, resetsAt, upgrade } = await $.Entitlement.check({ customer: 'customer_1', verb: 'verb_1' }) ``` **CLI** ```bash npx startup-builder do Entitlement.check --json '{"customer":"customer_1","verb":"verb_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Entitlement.check({ customer: 'customer_1', verb: 'verb_1' })" } } ``` Guides that call it: [Check what a customer can do](/products/offers/check-what-a-customer-can-do). # Entitlement URL: /business/nouns/entitlement · Id: `noun:entitlement` > An Entitlement is what a Customer gets from an accepted Offer: a Verb on a Noun in its Tenant, optionally bounded by a Limit. An Entitlement is what a [Customer](/business/nouns/customer) gets from an accepted [Offer](/business/nouns/offer): a [Verb](/business/nouns/verb) on a [Noun](/business/nouns/noun) in its [Tenant](/business/nouns/tenant), optionally bounded by a [Limit](/business/nouns/limit). ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `verb` | [Verb](/business/nouns/verb) | Yes | The Verb it grants. | | `limit` | [Limit](/business/nouns/limit) | No | The Limit that bounds it. | | `kind` | `string` | No | Computed, never set: `feature`, or `limit` when a Limit bounds it. | ## Object ```json { "$id": "https://api.sb/patentpad.com/entitlements/entitlement_1", "$type": "Entitlement", "verb": "verb_1", "limit": "limit_1", "kind": "feature" } ``` ## Relationships - An Entitlement **is granted by** one [Offer](/business/nouns/offer): an accepted [Offer](/business/nouns/offer) grants Entitlements, each a [Verb](/business/nouns/verb) on a [Noun](/business/nouns/noun), optionally bounded by a [Limit](/business/nouns/limit). `grantedBy`, inverse [`grants`](/business/nouns/offer#rel-grants). - An Entitlement **is held by** one [Customer](/business/nouns/customer): a [Customer](/business/nouns/customer)’s Entitlements are what it may do right now, granted by the [Offers](/business/nouns/offer) it accepted. `heldBy`, inverse [`holds`](/business/nouns/customer#rel-holds). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Entitlement.check](/business/nouns/entitlement/check) | Check says whether a Customer may call a Verb now, how much of its Limit remains, when that resets, and which Offer lifts it. | [Agent](/business/nouns/agent) | [`Entitlement.checked`](/business/events/Entitlement.checked) | Two-way: `try`, `send`, `do` | | [Entitlement.create](/business/nouns/entitlement/create) | Creates an Entitlement. Inherited from [Noun](/business/nouns/noun). | None. | `Entitlement.created` | Two-way: `try`, `send`, `do` | | [Entitlement.get](/business/nouns/entitlement/get) | Returns one Entitlement by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Entitlement.list](/business/nouns/entitlement/list) | Returns Entitlements, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Entitlement.update](/business/nouns/entitlement/update) | Changes the given properties of an Entitlement. Inherited from [Noun](/business/nouns/noun). | None. | `Entitlement.updated` | Two-way: `try`, `send`, `do` | | [Entitlement.delete](/business/nouns/entitlement/delete) | Deletes an Entitlement; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Entitlement.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Entitlement.create` | Yes | Yes | Yes | No | | `Entitlement.get` | Yes | Yes | Yes | Yes | | `Entitlement.list` | Yes | Yes | Yes | Yes | | `Entitlement.update` | Yes | Yes | Yes | No | | `Entitlement.delete` | Yes | Yes | Yes | No | | `Entitlement.check` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Check the latest entitlement with a customer and a verb. ``` **API** ```bash curl -X POST https://api.sb/ledgerlark.com/entitlements/check \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"customer":"customer_1","verb":"verb_1"}' ``` ```json { "api": "https://api.sb/ledgerlark.com", "allowed": true, "entitlement": { "$id": "https://api.sb/ledgerlark.com/entitlements/entitlement_1", "$type": "Entitlement", "verb": "verb_1" }, "remaining": 1, "resetsAt": "2026-10-22T12:00:00Z", "upgrade": { "$id": "https://api.sb/ledgerlark.com/offers/offer_1", "$type": "Offer", "price": { "amount": 400, "currency": "USD" } }, "action": { "$id": "https://api.sb/ledgerlark.com/actions/action_1", "operation": "Entitlement.check", "status": "done" }, "links": { "self": "https://api.sb/ledgerlark.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { allowed, entitlement, remaining, resetsAt, upgrade } = await $.Entitlement.check({ customer: 'customer_1', verb: 'verb_1' }) ``` **CLI** ```bash npx startup-builder do Entitlement.check --json '{"customer":"customer_1","verb":"verb_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Entitlement.check({ customer: 'customer_1', verb: 'verb_1' })" } } ``` ## Example A dental office on the $99 plan holds an Entitlement to send appointment reminders from its [Tenant](/business/nouns/tenant). A [Limit](/business/nouns/limit) bounds it at 1,000 reminders a month. # Entry URL: /business/nouns/entry · Id: `noun:entry` > An Entry is one line of a double-entry posting: an amount to one account in the chart of accounts, caused by one Event. An Entry is one line of a double-entry posting: an amount to one account in the chart of accounts, caused by one [Event](/business/nouns/event). ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `account` | `string` | Yes | The code of the account in the chart of accounts, such as revenue or cash. | | `amount` | `money` | Yes | The amount and currency. | | `direction` | `string` | Yes | One of `debit` or `credit`. | | `startup` | [Startup](/business/nouns/startup) | Yes | The Startup whose books the Entry belongs to. | | `counterparty` | [Startup](/business/nouns/startup) | No | The sibling Startup on the other side of an intercompany Entry; empty for outside parties. | ## Object ```json { "$id": "https://api.sb/tutorloop.com/entries/entry_1", "$type": "Entry", "account": "cash", "amount": { "amount": 60, "currency": "USD" }, "direction": "debit", "startup": "startup_1", "counterparty": "startup_1" } ``` ## Relationships - An Entry **is caused by** one [Event](/business/nouns/event): every ledger Entry traces to the one [Event](/business/nouns/event) that caused it, such as `Order.paid`. `causedBy`, inverse [`causes`](/business/nouns/event#rel-causes). - An Entry **falls in** one [Period](/business/nouns/period): an Entry posts to the month its [Event](/business/nouns/event) happened; closing the [Period](/business/nouns/period) locks it. `fallsIn`, inverse [`entries`](/business/nouns/period#rel-entries). - An Entry **posts to** one [Account](/business/nouns/account): each Entry posts to one [Account](/business/nouns/account), and an Account’s balance is the sum of its Entries. `postsTo`, inverse [`entries`](/business/nouns/account#rel-entries). - An Entry **is reconciled by** many [Transactions](/business/nouns/transaction): the ledger Entries the [Transaction](/business/nouns/transaction) settles, matched during reconciliation. `reconciledBy`, inverse [`reconciles`](/business/nouns/transaction#rel-reconciles). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Entry.post](/business/nouns/entry/post) | Post records a manual Entry pair that no Verb caused, once a second Role approves it. | [Finance Lead](/agents/finance/finance-lead) | [`Entry.posted`](/business/events/Entry.posted) | One-way: `send`, `do` | | [Entry.settle](/business/nouns/entry/settle) | Settle nets a Period’s intercompany Entries between two Companies into one transfer through Stripe and reconciles both sides. | [Treasurer](/agents/finance/treasurer) | [`Entry.settled`](/business/events/Entry.settled) | One-way (money): `send`, `do` | | [Entry.get](/business/nouns/entry/get) | Returns one Entry by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Entry.list](/business/nouns/entry/list) | Returns Entries, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | An Entry is kept forever and never edited: it has no `update` or `delete`. ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Entry.get` | Yes | Yes | Yes | Yes | | `Entry.list` | Yes | Yes | Yes | Yes | | `Entry.post` | Yes | No | No | No | | `Entry.settle` | Yes | No | No | No | ## Call it **Ask** ```text Post the latest entry. ``` **API** ```bash curl -X POST https://api.sb/kilnbakery.com/entries/post \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"debit":"Example debit","credit":"Example credit","amount":{"amount":9,"currency":"USD"},"memo":"Example memo"}' ``` ```json { "api": "https://api.sb/kilnbakery.com", "entry": { "$id": "https://api.sb/kilnbakery.com/entries/entry_1", "$type": "Entry", "account": "cash", "amount": { "amount": 9, "currency": "USD" }, "direction": "debit", "startup": "startup_1" }, "action": { "$id": "https://api.sb/kilnbakery.com/actions/action_1", "operation": "Entry.post", "status": "done" }, "links": { "self": "https://api.sb/kilnbakery.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const entry = await $.Entry.post({ debit: 'Example debit', credit: 'Example credit', amount: { amount: 9, currency: 'USD' }, memo: 'Example memo' }) ``` **CLI** ```bash npx startup-builder do Entry.post --json '{"debit":"Example debit","credit":"Example credit","amount":{"amount":9,"currency":"USD"},"memo":"Example memo"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Entry.post({ debit: 'Example debit', credit: 'Example credit', amount: { amount: 9, currency: 'USD' }, memo: 'Example memo' })" } } ``` ## Example A $49 payment posts two Entries: $49 to cash and $49 to revenue. The `Invoice.paid` Event causes both. # post URL: /business/nouns/entry/post · Id: `verb:Entry.post` · Call: `await $.Entry.post({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Post records a manual Entry pair that no Verb caused, once a second Role approves it. [Post](/business/nouns/post) records a manual [Entry](/business/nouns/entry) pair that no [Verb](/business/nouns/verb) caused, once a second [Role](/business/nouns/role) approves it. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `debit` | `string` | Yes | The account code debited, such as `expense.hosting`. | | `credit` | `string` | Yes | The account code credited. | | `amount` | `money` | Yes | The amount and currency. | | `memo` | `text` | Yes | Why the Entry exists. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `entry` | [Entry](/business/nouns/entry) | Yes | The debit Entry; its credit pair links to it. | ## Effects - Emits [`Entry.posted`](/business/events/Entry.posted). - Performed by the [Finance Lead](/agents/finance/finance-lead). - One-way: it waits out its delay window, and runs in the `send` and `do` modes. - Waits for an Approval from a Role other than the one that asked. - A correction to a locked Period posts to the next open Period. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Entry.post](/business/nouns/entry/post) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Medium: one-way, bounded | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | 1 business hour, in which a watcher can pause, redirect or cancel it; then it runs. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Treasurer](/agents/finance/treasurer). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Post the latest entry. ``` **API** ```bash curl -X POST https://api.sb/kilnbakery.com/entries/post \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"debit":"Example debit","credit":"Example credit","amount":{"amount":9,"currency":"USD"},"memo":"Example memo"}' ``` ```json { "api": "https://api.sb/kilnbakery.com", "entry": { "$id": "https://api.sb/kilnbakery.com/entries/entry_1", "$type": "Entry", "account": "cash", "amount": { "amount": 9, "currency": "USD" }, "direction": "debit", "startup": "startup_1" }, "action": { "$id": "https://api.sb/kilnbakery.com/actions/action_1", "operation": "Entry.post", "status": "done" }, "links": { "self": "https://api.sb/kilnbakery.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const entry = await $.Entry.post({ debit: 'Example debit', credit: 'Example credit', amount: { amount: 9, currency: 'USD' }, memo: 'Example memo' }) ``` **CLI** ```bash npx startup-builder do Entry.post --json '{"debit":"Example debit","credit":"Example credit","amount":{"amount":9,"currency":"USD"},"memo":"Example memo"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Entry.post({ debit: 'Example debit', credit: 'Example credit', amount: { amount: 9, currency: 'USD' }, memo: 'Example memo' })" } } ``` # settle URL: /business/nouns/entry/settle · Id: `verb:Entry.settle` · Call: `await $.Entry.settle({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Settle nets a Period’s intercompany Entries between two Companies into one transfer through Stripe and reconciles both sides. Settle nets a [Period](/business/nouns/period)’s intercompany [Entries](/business/nouns/entry) between two [Companies](/business/nouns/company) into one transfer through Stripe and reconciles both sides. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `period` | [Period](/business/nouns/period) | Yes | The closed Period whose intercompany pairs settle. | | `from` | [Company](/business/nouns/company) | Yes | The Company that owes the net amount. | | `to` | [Company](/business/nouns/company) | Yes | The Company that receives it. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `transaction` | [Transaction](/business/nouns/transaction) | Yes | The one transfer that settles every pair. | | `entry` | [Entry](/business/nouns/entry) | Yes | The intercompany Entry, now settled. | ## Effects - Emits [`Entry.settled`](/business/events/Entry.settled). - Performed by the [Treasurer](/agents/finance/treasurer). - One-way (money): it waits out its delay window, and runs in the `send` and `do` modes. - Runs monthly, once both Companies have closed the Period. - Links every settled pair to the Transaction that settled it. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Entry.settle](/business/nouns/entry/settle) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Medium: one-way, bounded (money) | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | 1 business hour, in which a watcher can pause, redirect or cancel it; then it runs. | | Limit | The spend [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) or [Mandate](/business/nouns/mandate) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Settle the latest entry with a period and a company and a company. ``` **API** ```bash curl -X POST https://api.sb/patentpad.com/entries/settle \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"period":"period_1","from":"company_1","to":"company_1"}' ``` ```json { "api": "https://api.sb/patentpad.com", "transaction": { "$id": "https://api.sb/patentpad.com/transactions/transaction_1", "$type": "Transaction", "kind": "charge", "amount": { "amount": 499, "currency": "USD" } }, "entry": { "$id": "https://api.sb/patentpad.com/entries/entry_1", "$type": "Entry", "account": "cash", "amount": { "amount": 499, "currency": "USD" }, "direction": "debit", "startup": "startup_1" }, "action": { "$id": "https://api.sb/patentpad.com/actions/action_1", "operation": "Entry.settle", "status": "done" }, "links": { "self": "https://api.sb/patentpad.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { transaction, entry } = await $.Entry.settle({ period: 'period_1', from: 'company_1', to: 'company_1' }) ``` **CLI** ```bash npx startup-builder do Entry.settle --json '{"period":"period_1","from":"company_1","to":"company_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Entry.settle({ period: 'period_1', from: 'company_1', to: 'company_1' })" } } ``` # Evaluator URL: /business/nouns/evaluator · Id: `noun:evaluator` > An Evaluator is a versioned Function that grades an output against a rubric and returns a verdict. An Evaluator is a versioned [Function](/business/nouns/function) that grades an output against a rubric and returns a verdict. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `rubric` | `text` | Yes | What it grades against. An agent never varies its own Evaluators. Never randomized. | | `integration` | [Integration](/business/nouns/integration) | No | The Integration whose outside run returns the verdict, such as a CI job; empty when the platform runs it. | | `required` | `boolean` | No | True when `Change.merge` refuses until this Evaluator passes on the Change’s head. Never randomized. |
Inherited from [Function](/business/nouns/function): 12 properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `kind` | `string` | Yes | One of `code`, `generative`, `agentic`, or `human`. | | `version` | `string` | No | The Version an Action runs, kept with the Action. | | `cascade` | `string[]` | No | Kinds tried in order when one declines, such as code, then a Human. | | `instructions` | `text` | No | For a generative or agentic Function, what it does and how. | | `model` | `string` | No | For a generative or agentic Function, the model it runs on. | | `tools` | list of [Verb](/business/nouns/verb) | No | For an agentic Function, the Verbs it may call; Permissions and Limits apply to each. | | `maxSteps` | `integer` | No | For an agentic Function, the most steps one Action may take. | | `budget` | `money` | No | The most one Action may spend; the Mandate’s Limits apply as well. | | `role` | [Role](/business/nouns/role) | No | For a human Function, the Role its Tasks go to. | | `form` | `json` | No | For a human Function, the form; generated from the Verb’s inputs and outputs when absent. | | `sla` | `string` | No | For a human Function, how long a Task may wait, as an ISO 8601 duration. | | `escalateTo` | [Role](/business/nouns/role) | No | For a human Function, the Role a Task moves to when the service level passes. |
## Object ```json { "$id": "https://api.sb/ledgerlark.com/evaluators/evaluator_1", "$type": "Evaluator", "kind": "code", "version": "Example version", "cascade": [ "Example cascade" ], "instructions": "Example instructions", "model": "Example model", "tools": [ "verb_1" ], "maxSteps": 1, "budget": { "amount": 400, "currency": "USD" }, "role": "role_1", "form": {}, "sla": "PT4H", "escalateTo": "role_1", "rubric": "Example rubric", "integration": "integration_1", "required": true } ``` ## Relationships - An Evaluator **grades** many [Verbs](/business/nouns/verb): the [Verbs](/business/nouns/verb) whose results the Evaluator scores against its rubric before they count as done. `grades`, inverse [`gradedBy`](/business/nouns/verb#rel-graded-by). - An Evaluator **verifies** many [Outcome Contracts](/business/nouns/outcome-contract): Evaluators grade delivered work against an [Outcome Contract](/business/nouns/outcome-contract)’s done state before the [Customer](/business/nouns/customer) accepts it. `verifies`, inverse [`verifiedBy`](/business/nouns/outcome-contract#rel-verified-by). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Evaluator.create](/business/nouns/evaluator/create) | Creates an Evaluator. Inherited from [Noun](/business/nouns/noun). | None. | `Evaluator.created` | Two-way: `try`, `send`, `do` | | [Evaluator.get](/business/nouns/evaluator/get) | Returns one Evaluator by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Evaluator.list](/business/nouns/evaluator/list) | Returns Evaluators, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Evaluator.update](/business/nouns/evaluator/update) | Changes the given properties of an Evaluator. Inherited from [Noun](/business/nouns/noun). | None. | `Evaluator.updated` | Two-way: `try`, `send`, `do` | | [Evaluator.delete](/business/nouns/evaluator/delete) | Deletes an Evaluator; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Evaluator.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Evaluator.create` | Yes | Yes | Yes | No | | `Evaluator.get` | Yes | Yes | Yes | Yes | | `Evaluator.list` | Yes | Yes | Yes | Yes | | `Evaluator.update` | Yes | Yes | Yes | No | | `Evaluator.delete` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Add an evaluator to PatentPad. ``` **API** ```bash curl -X POST https://api.sb/patentpad.com/evaluators \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"kind":"code","rubric":"Example rubric"}' ``` ```json { "api": "https://api.sb/patentpad.com", "evaluator": { "$id": "https://api.sb/patentpad.com/evaluators/evaluator_1", "$type": "Evaluator", "kind": "code", "rubric": "Example rubric" }, "action": { "$id": "https://api.sb/patentpad.com/actions/action_1", "operation": "Evaluator.create", "status": "done" }, "links": { "self": "https://api.sb/patentpad.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const evaluator = await $.Evaluator.create({ kind: 'code', rubric: 'Example rubric' }) ``` **CLI** ```bash npx startup-builder do Evaluator.create --json '{"kind":"code","rubric":"Example rubric"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Evaluator.create({ kind: 'code', rubric: 'Example rubric' })" } } ``` ## Example An Evaluator grades each support answer against a rubric of accuracy, tone, and policy, and returns pass or fail with the reason. # capture URL: /business/nouns/event/capture · Id: `verb:Event.capture` · Call: `await $.Event.capture({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Capture records an Event from a Site, App or API call that no Verb emits, such as a page view or a click. Capture records an [Event](/business/nouns/event) from a [Site](/business/nouns/site), [App](/business/nouns/app) or API call that no [Verb](/business/nouns/verb) emits, such as a page view or a click. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `name` | `string` | Yes | The Event name, `Noun.pastTense`. | | `data` | `json` | No | The Event’s properties. | | `visitor` | [Visitor](/business/nouns/visitor) | No | The Visitor it happened to, when the person is not known. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `event` | [Event](/business/nouns/event) | Yes | The captured Event. | ## Effects - Emits [`Event.captured`](/business/events/Event.captured). - Performed by the [Analyst](/agents/marketing/analyst). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Every Verb emits its own Event, so the registry is the tracking plan. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Event.capture](/business/nouns/event/capture) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Capture the latest event. ``` **API** ```bash curl -X POST https://api.sb/tutorloop.com/events/capture \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"name":"TutorLoop"}' ``` ```json { "api": "https://api.sb/tutorloop.com", "event": { "$id": "https://api.sb/tutorloop.com/events/event_1", "$type": "Event", "name": "TutorLoop", "at": "2026-10-22T12:00:00Z" }, "action": { "$id": "https://api.sb/tutorloop.com/actions/action_1", "operation": "Event.capture", "status": "done" }, "links": { "self": "https://api.sb/tutorloop.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const event = await $.Event.capture({ name: 'TutorLoop' }) ``` **CLI** ```bash npx startup-builder do Event.capture --json '{"name":"TutorLoop"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Event.capture({ name: 'TutorLoop' })" } } ``` # Event URL: /business/nouns/event · Id: `noun:event` > An Event is the immutable record of something that happened to a Thing, named by its Noun and past-tense Verb. An Event is the immutable record of something that happened to a [Thing](/business/nouns/thing), named by its [Noun](/business/nouns/noun) and past-tense [Verb](/business/nouns/verb). [Metrics](/business/nouns/metric), [Triggers](/business/nouns/trigger) and [Watches](/business/nouns/watch) read Events, so every number and every automation traces back to one. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `name` | `string` | Yes | The Noun and the event form of its Verb, such as `Order.placed`. | | `at` | `datetime` | Yes | When it happened. | | `data` | `json` | No | The Thing as the Action left it. | | `seq` | `integer` | No | Its position in the namespace, one more than the Event before; any seq is a cursor into the history. | ## Object ```json { "$id": "https://api.sb/quietcopy.com/events/event_1", "$type": "Event", "name": "QuietCopy", "at": "2026-10-22T12:00:00Z", "data": {}, "seq": 1 } ``` ## Relationships - An Event **causes** many [Entries](/business/nouns/entry): every ledger [Entry](/business/nouns/entry) traces to the one Event that caused it, such as `Order.paid`. `causes`, inverse [`causedBy`](/business/nouns/entry#rel-caused-by). - An Event **is delivered by** many [Watches](/business/nouns/watch): a [Watch](/business/nouns/watch) delivers each matching Event to its URL, signed, retried and replayable. `deliveredBy`, inverse [`delivers`](/business/nouns/watch#rel-delivers). - An Event **is emitted by** one [Action](/business/nouns/action): a completed [Action](/business/nouns/action) emits its Events, which [Triggers](/business/nouns/trigger), [Watches](/business/nouns/watch) and [Metrics](/business/nouns/metric) read. `emittedBy`, inverse [`emits`](/business/nouns/action#rel-emits). - An Event **feeds** many [Metrics](/business/nouns/metric): a [Metric](/business/nouns/metric) derives from Events and is never typed in. `feeds`, inverse [`computedFrom`](/business/nouns/metric#rel-computed-from). - An Event **fires** many [Triggers](/business/nouns/trigger): a [Trigger](/business/nouns/trigger) fires each time an Event matching its selector happens. `fires`, inverse [`firesOn`](/business/nouns/trigger#rel-fires-on). - An Event **is metered by** many [Meters](/business/nouns/meter): the Events the [Meter](/business/nouns/meter) counts toward usage billing. `meteredBy`, inverse [`counts`](/business/nouns/meter#rel-counts). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Event.capture](/business/nouns/event/capture) | Capture records an Event from a Site, App or API call that no Verb emits, such as a page view or a click. | [Analyst](/agents/marketing/analyst) | [`Event.captured`](/business/events/Event.captured) | Two-way: `try`, `send`, `do` | | [Event.create](/business/nouns/event/create) | Creates an Event. Inherited from [Noun](/business/nouns/noun). | None. | `Event.created` | Two-way: `try`, `send`, `do` | | [Event.get](/business/nouns/event/get) | Returns one Event by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Event.list](/business/nouns/event/list) | Returns Events, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | An Event is kept forever and never edited: it has no `update` or `delete`. ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Event.create` | Yes | Yes | Yes | No | | `Event.get` | Yes | Yes | Yes | Yes | | `Event.list` | Yes | Yes | Yes | Yes | | `Event.capture` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Capture the latest event. ``` **API** ```bash curl -X POST https://api.sb/tutorloop.com/events/capture \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"name":"TutorLoop"}' ``` ```json { "api": "https://api.sb/tutorloop.com", "event": { "$id": "https://api.sb/tutorloop.com/events/event_1", "$type": "Event", "name": "TutorLoop", "at": "2026-10-22T12:00:00Z" }, "action": { "$id": "https://api.sb/tutorloop.com/actions/action_1", "operation": "Event.capture", "status": "done" }, "links": { "self": "https://api.sb/tutorloop.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const event = await $.Event.capture({ name: 'TutorLoop' }) ``` **CLI** ```bash npx startup-builder do Event.capture --json '{"name":"TutorLoop"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Event.capture({ name: 'TutorLoop' })" } } ``` ## Example `Invoice.paid` records that [Invoice](/business/nouns/invoice) 1042 was paid $49 at 14:02. It feeds the monthly recurring revenue Metric and fires the receipt Trigger, and no later [Action](/business/nouns/action) alters it. # Evidence URL: /business/nouns/evidence · Id: `noun:evidence` > Evidence is a recorded quote, reading, or artifact that supports or refutes a claim, graded as behavior, commitment, or opinion. Evidence is a recorded quote, reading, or artifact that supports or refutes a claim, graded as behavior, commitment, or opinion. Behavior outranks commitment, and an opinion weighs zero. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `grade` | `string` | Yes | One of `Behavior`, `Commitment`, or `Opinion`. An Opinion weighs zero. | | `quote` | `text` | No | The words or reading, verbatim. | | `source` | `string` | No | Who or what it came from: an Interview, an Experiment, or a Metric reading. | | `binds` | `string` | No | The slot it grades, as `Hypothesis#`. | | `force` | `string` | No | One of `push`, `pull`, `anxiety`, or `habit`: the switching force it shows. | | `observedAt` | `datetime` | No | When it was observed. | | `distinctIcpMembers` | `integer` | No | How many distinct ICP members it represents. | | `outside` | `boolean` | No | Computed: true when its source shares no owner, Studio account, Agreement, or sibling chain with the Startup. | | `askedBy` | [Party](/business/nouns/party) | No | The Customer or Contact who asked through an App, the Portal or an Agent; their ask is Opinion grade. | | `stance` | `string` | No | Whether it supports or refutes the slot it binds; a cancel refutes the slot its reason tests. | ## Object ```json { "$id": "https://api.sb/routewise.dev/evidence/evidence_1", "$type": "Evidence", "grade": "Behavior", "quote": "Example quote", "source": "Example source", "binds": "Example binds", "force": "push", "observedAt": "2026-10-22T12:00:00Z", "distinctIcpMembers": 1, "outside": true, "askedBy": "party_1", "stance": "supports" } ``` ## Relationships - A piece of Evidence **bears on** many [Hypotheses](/business/nouns/hypothesis): Evidence supports or refutes [Hypotheses](/business/nouns/hypothesis); the strongest outside Evidence sets each Hypothesis grade. `bearsOn`, inverse [`evidence`](/business/nouns/hypothesis#rel-evidence). - A piece of Evidence **is cited by** many [Disputes](/business/nouns/dispute): the Evidence each side submits on the [Dispute](/business/nouns/dispute), frozen once submitted. `citedBy`, inverse [`cites`](/business/nouns/dispute#rel-cites). - A piece of Evidence **documents** many [Problems](/business/nouns/problem): Evidence shows a [Problem](/business/nouns/problem) in the words or behavior of the [ICP](/business/nouns/icp). `documents`, inverse [`documentedBy`](/business/nouns/problem#rel-documented-by). - A piece of Evidence **is yielded by** one [Interview](/business/nouns/interview): an [Interview](/business/nouns/interview) captures quotes and commitments, each graded as Evidence. `yieldedBy`, inverse [`yields`](/business/nouns/interview#rel-yields). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Evidence.create](/business/nouns/evidence/create) | Creates an Evidence. Inherited from [Noun](/business/nouns/noun). | None. | `Evidence.created` | Two-way: `try`, `send`, `do` | | [Evidence.get](/business/nouns/evidence/get) | Returns one Evidence by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Evidence.list](/business/nouns/evidence/list) | Returns Evidence, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | A piece of Evidence is kept forever and never edited: it has no `update` or `delete`. ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Evidence.create` | Yes | Yes | Yes | No | | `Evidence.get` | Yes | Yes | Yes | Yes | | `Evidence.list` | Yes | Yes | Yes | Yes | ## Call it **Ask** ```text Add an evidence to LedgerLark. ``` **API** ```bash curl -X POST https://api.sb/ledgerlark.com/evidence \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"grade":"Behavior"}' ``` ```json { "api": "https://api.sb/ledgerlark.com", "evidence": { "$id": "https://api.sb/ledgerlark.com/evidence/evidence_1", "$type": "Evidence", "grade": "Behavior" }, "action": { "$id": "https://api.sb/ledgerlark.com/actions/action_1", "operation": "Evidence.create", "status": "done" }, "links": { "self": "https://api.sb/ledgerlark.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const evidence = await $.Evidence.create({ grade: 'Behavior' }) ``` **CLI** ```bash npx startup-builder do Evidence.create --json '{"grade":"Behavior"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Evidence.create({ grade: 'Behavior' })" } } ``` ## Example A dental office manager shows her log of 60 no-shows a month at $180 each. The log is Evidence with `grade: Behavior` on the [Problem](/business/nouns/problem), and it bears on the pricing [Hypothesis](/business/nouns/hypothesis). # conclude URL: /business/nouns/experiment/conclude · Id: `verb:Experiment.conclude` · Call: `await $.Experiment.conclude({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Conclude ends an Experiment with a decision to ship, kill, or iterate, recorded as a Decision. Conclude ends an [Experiment](/business/nouns/experiment) with a decision to ship, kill, or iterate, recorded as a [Decision](/business/nouns/decision). ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `experiment` | [Experiment](/business/nouns/experiment) | Yes | The running Experiment. | | `decision` | `string` | Yes | One of `ship`, `kill`, `iterate`. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `decision` | [Decision](/business/nouns/decision) | Yes | The recorded Decision. | | `experiment` | [Experiment](/business/nouns/experiment) | Yes | The Experiment, now concluded. | ## Effects - Emits [`Experiment.concluded`](/business/events/Experiment.concluded). - Performed by the [Strategist](/agents/founding/strategist). - Moves each tested Hypothesis to supported or refuted. - Ships the winning variant when the decision is `ship`. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The input does not match the schema of the operation. | [`invalid-input`](/code/api/errors/invalid-input) | Read the schema of the operation, then send every required field with the right type. | [Experiment.conclude](/business/nouns/experiment/conclude) | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Experiment.conclude](/business/nouns/experiment/conclude) | | The record is not in a state that allows this Verb, so the call is refused. | [`refused`](/code/api/errors/refused) | Read the record, run the Verb that moves it to an allowed state, then retry. | [Experiment.conclude](/business/nouns/experiment/conclude) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Conclude the latest experiment. ``` **API** ```bash curl -X POST https://api.sb/kilnbakery.com/experiments/experiment_1/conclude \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"decision":"ship"}' ``` ```json { "api": "https://api.sb/kilnbakery.com", "decision": { "$id": "https://api.sb/kilnbakery.com/decisions/decision_1", "$type": "Decision", "choice": "Example choice", "reason": "Example reason" }, "experiment": { "$id": "https://api.sb/kilnbakery.com/experiments/experiment_1", "$type": "Experiment", "variants": {} }, "action": { "$id": "https://api.sb/kilnbakery.com/actions/action_1", "operation": "Experiment.conclude", "status": "done" }, "links": { "self": "https://api.sb/kilnbakery.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { decision, experiment } = await $.Experiment.conclude({ experiment: 'experiment_1', decision: 'ship' }) ``` **CLI** ```bash npx startup-builder do Experiment.conclude --json '{"experiment":"experiment_1","decision":"ship"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Experiment.conclude({ experiment: 'experiment_1', decision: 'ship' })" } } ``` # Experiment URL: /business/nouns/experiment · Id: `noun:experiment` > An Experiment is a test of a Hypothesis that varies copy or behavior through Flags and judges the variants by a primary Metric. An Experiment is a test of a [Hypothesis](/business/nouns/hypothesis) that varies copy or behavior through [Flags](/business/nouns/flag) and judges the [Variants](/business/nouns/variant) by a primary [Metric](/business/nouns/metric). It ends in a `decision`: ship, kill, or iterate. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `variants` | `json` | Yes | The variants and their split. | | `decision` | `string` | No | One of `ship`, `kill`, or `iterate`. | ## Object ```json { "$id": "https://api.sb/ledgerlark.com/experiments/experiment_1", "$type": "Experiment", "variants": {}, "decision": "ship" } ``` ## Relationships - An Experiment **assigns with** many [Flags](/business/nouns/flag): [Flags](/business/nouns/flag) split units across an Experiment’s [Variants](/business/nouns/variant) and log each assignment with its propensity. `assignsWith`, inverse [`assigns`](/business/nouns/flag#rel-assigns). - An Experiment **measures** many [Metrics](/business/nouns/metric): one primary [Metric](/business/nouns/metric) judges an Experiment’s [Variants](/business/nouns/variant); guardrail Metrics stop it. `measures`, inverse [`measuredBy`](/business/nouns/metric#rel-measured-by). - An Experiment **offers** many [Variants](/business/nouns/variant): the [Variants](/business/nouns/variant) the Experiment can assign, the control among them. `offers`, inverse [`offeredBy`](/business/nouns/variant#rel-offered-by). - An Experiment **has** many [Readouts](/business/nouns/readout): the Experiment the result belongs to; the learn step drafts the next [Variant](/business/nouns/variant) from it. `readouts`, inverse [`reads`](/business/nouns/readout#rel-reads). - An Experiment **tests** one [Hypothesis](/business/nouns/hypothesis): each Experiment settles one [Hypothesis](/business/nouns/hypothesis); many Experiments test one Hypothesis in turn. `tests`, inverse [`testedBy`](/business/nouns/hypothesis#rel-tested-by). ## Lifecycle | State | Meaning | Moves to | | --- | --- | --- | | `draft` (first) | Its variants and Metrics are set, and no traffic is split yet. | `running` by [Experiment.start](/business/nouns/experiment/start) | | `running` | Traffic is split across its variants while its Metrics are measured. | `concluded` by [Experiment.conclude](/business/nouns/experiment/conclude) | | `concluded` | It ended with a Decision to ship, kill, or iterate. | None: it ends here. | ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Experiment.conclude](/business/nouns/experiment/conclude) | Conclude ends an Experiment with a decision to ship, kill, or iterate, recorded as a Decision. | [Strategist](/agents/founding/strategist) | [`Experiment.concluded`](/business/events/Experiment.concluded) | None. | | [Experiment.start](/business/nouns/experiment/start) | Start opens an Experiment, splits traffic across its variants, and begins measuring its primary and guardrail Metrics. | [Strategist](/agents/founding/strategist) | [`Experiment.started`](/business/events/Experiment.started) | None. | | [Experiment.create](/business/nouns/experiment/create) | Creates an Experiment. Inherited from [Noun](/business/nouns/noun). | None. | `Experiment.created` | Two-way: `try`, `send`, `do` | | [Experiment.get](/business/nouns/experiment/get) | Returns one Experiment by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Experiment.list](/business/nouns/experiment/list) | Returns Experiments, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | An Experiment is kept forever and never edited: it has no `update` or `delete`. ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Experiment.create` | Yes | Yes | Yes | No | | `Experiment.get` | Yes | Yes | Yes | Yes | | `Experiment.list` | Yes | Yes | Yes | Yes | | `Experiment.conclude` | Yes | Yes | Yes | No | | `Experiment.start` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Start the latest experiment. ``` **API** ```bash curl -X POST https://api.sb/patentpad.com/experiments/experiment_1/start \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/patentpad.com", "experiment": { "$id": "https://api.sb/patentpad.com/experiments/experiment_1", "$type": "Experiment", "variants": {} }, "action": { "$id": "https://api.sb/patentpad.com/actions/action_1", "operation": "Experiment.start", "status": "done" }, "links": { "self": "https://api.sb/patentpad.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const experiment = await $.Experiment.start({ experiment: 'experiment_1' }) ``` **CLI** ```bash npx startup-builder do Experiment.start --json '{"experiment":"experiment_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Experiment.start({ experiment: 'experiment_1' })" } } ``` ## Example An Experiment tests whether a $0 tier raises paid conversion. A Flag shows the tier to half of new [Visitors](/business/nouns/visitor); paid conversion at 30 days decides, and the `decision` reads `ship`. # start URL: /business/nouns/experiment/start · Id: `verb:Experiment.start` · Call: `await $.Experiment.start({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Start opens an Experiment, splits traffic across its variants, and begins measuring its primary and guardrail Metrics. Start opens an [Experiment](/business/nouns/experiment), splits traffic across its variants, and begins measuring its primary and guardrail [Metrics](/business/nouns/metric). ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `experiment` | [Experiment](/business/nouns/experiment) | Yes | The Experiment to open. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `experiment` | [Experiment](/business/nouns/experiment) | Yes | The running Experiment. | ## Effects - Emits [`Experiment.started`](/business/events/Experiment.started). - Performed by the [Strategist](/agents/founding/strategist). ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The input does not match the schema of the operation. | [`invalid-input`](/code/api/errors/invalid-input) | Read the schema of the operation, then send every required field with the right type. | [Experiment.start](/business/nouns/experiment/start) | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Experiment.start](/business/nouns/experiment/start) | | The record is not in a state that allows this Verb, so the call is refused. | [`refused`](/code/api/errors/refused) | Read the record, run the Verb that moves it to an allowed state, then retry. | [Experiment.start](/business/nouns/experiment/start) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Start the latest experiment. ``` **API** ```bash curl -X POST https://api.sb/patentpad.com/experiments/experiment_1/start \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/patentpad.com", "experiment": { "$id": "https://api.sb/patentpad.com/experiments/experiment_1", "$type": "Experiment", "variants": {} }, "action": { "$id": "https://api.sb/patentpad.com/actions/action_1", "operation": "Experiment.start", "status": "done" }, "links": { "self": "https://api.sb/patentpad.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const experiment = await $.Experiment.start({ experiment: 'experiment_1' }) ``` **CLI** ```bash npx startup-builder do Experiment.start --json '{"experiment":"experiment_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Experiment.start({ experiment: 'experiment_1' })" } } ``` Guides that call it: [Spend $200 to test faster](/start/guides/spend-200-to-test-faster), [Test two onboarding emails](/workflows/guides/test-two-onboarding-emails), [Test a new way of answering customers](/agents/test-new-support-instructions). # Exposure URL: /business/nouns/exposure · Id: `noun:exposure` > An Exposure is the moment one unit meets the Variant its Flag assigned, logged with every option and its propensity. An Exposure is the moment one unit meets the [Variant](/business/nouns/variant) its [Flag](/business/nouns/flag) assigned, logged with every option and its propensity. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `unit` | `string` | Yes | What was randomized: a Visitor, a Customer, a request, or an agent choice. | | `options` | `json` | Yes | Every Variant that was possible at that moment. | | `propensity` | `number` | Yes | The probability the assigned Variant had, kept for later estimates. | | `at` | `datetime` | Yes | When the unit met the Variant. | | `triggered` | `boolean` | No | True when the unit reached the point the Variant changes. | ## Object ```json { "$id": "https://api.sb/patentpad.com/exposures/exposure_1", "$type": "Exposure", "unit": "Example unit", "options": {}, "propensity": 1, "at": "2026-10-22T12:00:00Z", "triggered": true } ``` ## Relationships - An Exposure **meets** one [Variant](/business/nouns/variant): the [Variant](/business/nouns/variant) the [Flag](/business/nouns/flag) assigned to this unit. `meets`, inverse [`exposures`](/business/nouns/variant#rel-exposures). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Exposure.create](/business/nouns/exposure/create) | Creates an Exposure. Inherited from [Noun](/business/nouns/noun). | None. | `Exposure.created` | Two-way: `try`, `send`, `do` | | [Exposure.get](/business/nouns/exposure/get) | Returns one Exposure by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Exposure.list](/business/nouns/exposure/list) | Returns Exposures, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | An Exposure is kept forever and never edited: it has no `update` or `delete`. ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Exposure.create` | Yes | Yes | Yes | No | | `Exposure.get` | Yes | Yes | Yes | Yes | | `Exposure.list` | Yes | Yes | Yes | Yes | ## Call it **Ask** ```text Add an exposure to ShiftNote. ``` **API** ```bash curl -X POST https://api.sb/shiftnote.app/exposures \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"unit":"Example unit","options":{},"propensity":1,"at":"2026-10-22T12:00:00Z"}' ``` ```json { "api": "https://api.sb/shiftnote.app", "exposure": { "$id": "https://api.sb/shiftnote.app/exposures/exposure_1", "$type": "Exposure", "unit": "Example unit", "options": {}, "propensity": 1, "at": "2026-10-22T12:00:00Z" }, "action": { "$id": "https://api.sb/shiftnote.app/actions/action_1", "operation": "Exposure.create", "status": "done" }, "links": { "self": "https://api.sb/shiftnote.app/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const exposure = await $.Exposure.create({ unit: 'Example unit', options: {}, propensity: 1, at: '2026-10-22T12:00:00Z' }) ``` **CLI** ```bash npx startup-builder do Exposure.create --json '{"unit":"Example unit","options":{},"propensity":1,"at":"2026-10-22T12:00:00Z"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Exposure.create({ unit: 'Example unit', options: {}, propensity: 1, at: '2026-10-22T12:00:00Z' })" } } ``` ## Example A [Visitor](/business/nouns/visitor) who scrolls to a tutoring site's pricing table meets its [Flag](/business/nouns/flag) split. One Exposure records both [Variants](/business/nouns/variant) as options, the challenger assigned at a propensity of 0.5. # edit URL: /business/nouns/file/edit · Id: `verb:File.edit` · Call: `await $.File.edit({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Edit makes a new File from an existing one by instruction, such as upscaling or animating a still, and leaves the source unchanged. Edit makes a new [File](/business/nouns/file) from an existing one by instruction, such as upscaling or animating a still, and leaves the source unchanged. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `file` | [File](/business/nouns/file) | Yes | The source File. | | `instruction` | `text` | Yes | What to change. | | `references` | list of [File](/business/nouns/file) | No | Further Files the edit follows. | | `format` | `json` | No | Aspect ratio, resolution, duration and file type of the result. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `file` | [File](/business/nouns/file) | Yes | The new File, which records its source. | ## Effects - Emits [`File.edited`](/business/events/File.edited). - Performed by the [Content Lead](/agents/marketing/content-lead). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Runs as a background Action and copies the result into Storage before `done`. - Never changes the source File. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [File.edit](/business/nouns/file/edit) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Edit the latest file. ``` **API** ```bash curl -X POST https://api.sb/tutorloop.com/files/file_1/edit \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"instruction":"Example instruction"}' ``` ```json { "api": "https://api.sb/tutorloop.com", "file": { "$id": "https://api.sb/tutorloop.com/files/file_1", "$type": "File", "contentType": "Example content type", "size": 1 }, "action": { "$id": "https://api.sb/tutorloop.com/actions/action_1", "operation": "File.edit", "status": "done" }, "links": { "self": "https://api.sb/tutorloop.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const file = await $.File.edit({ file: 'file_1', instruction: 'Example instruction' }) ``` **CLI** ```bash npx startup-builder do File.edit --json '{"file":"file_1","instruction":"Example instruction"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.File.edit({ file: 'file_1', instruction: 'Example instruction' })" } } ``` # generate URL: /business/nouns/file/generate · Id: `verb:File.generate` · Call: `await $.File.generate({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Generate makes an image, video, speech or music File from a prompt and reference Files, and records how it was made. Generate makes an image, video, speech or music [File](/business/nouns/file) from a prompt and reference Files, and records how it was made. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `kind` | `string` | Yes | What to make. | | `prompt` | `text` | Yes | What to make, or for `speech` the text to speak. | | `references` | list of [File](/business/nouns/file) | No | Files the output follows, such as a product photo or a first frame. | | `voice` | [Voice](/business/nouns/voice) | No | The Voice that speaks, for `speech`. | | `format` | `json` | No | Aspect ratio, resolution, duration and file type. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `file` | [File](/business/nouns/file) | Yes | The generated File, its bytes in Storage and its provenance recorded. | ## Effects - Emits [`File.generated`](/business/events/File.generated). - Performed by the [Content Lead](/agents/marketing/content-lead). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Runs as a background Action that waits with reason `running` until the upstream finishes. - Copies the result bytes into Storage before the Action is `done`; an upstream link is never the record. - Posts no Cost when generation fails and ends `refused` when the upstream declines the prompt. - Canceling the Action cancels the upstream task. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [File.generate](/business/nouns/file/generate) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Generate the latest file. ``` **API** ```bash curl -X POST https://api.sb/patentpad.com/files/generate \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"kind":"image","prompt":"Example prompt"}' ``` ```json { "api": "https://api.sb/patentpad.com", "file": { "$id": "https://api.sb/patentpad.com/files/file_1", "$type": "File", "contentType": "Example content type", "size": 1 }, "action": { "$id": "https://api.sb/patentpad.com/actions/action_1", "operation": "File.generate", "status": "done" }, "links": { "self": "https://api.sb/patentpad.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const file = await $.File.generate({ kind: 'image', prompt: 'Example prompt' }) ``` **CLI** ```bash npx startup-builder do File.generate --json '{"kind":"image","prompt":"Example prompt"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.File.generate({ kind: 'image', prompt: 'Example prompt' })" } } ``` # File URL: /business/nouns/file · Id: `noun:file` > A File is the stored bytes of an upload or a rendering. A File is the stored bytes of an upload or a rendering. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `contentType` | `string` | Yes | The media type, such as `application/pdf`. | | `size` | `integer` | Yes | The size in bytes. | | `name` | `string` | No | The file name it was uploaded with. | | `visibility` | `string` | No | Who may read it: `Owner`, `Customer`, or `Public`. The default is `Owner`. | | `uploadUrl` | `url` | No | The signed URL to upload the bytes to, returned by `File.create`. | ## Object ```json { "$id": "https://api.sb/tutorloop.com/files/file_1", "$type": "File", "contentType": "Example content type", "size": 1, "name": "TutorLoop", "visibility": "Owner", "uploadUrl": "https://tutorloop.com" } ``` ## Relationships - A File **is an export of** one [Document](/business/nouns/document): each rendering of a [Document](/business/nouns/document) to a format, such as PDF, is stored as a File. `exportOf`, inverse [`exportsTo`](/business/nouns/document#rel-exports-to). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [File.edit](/business/nouns/file/edit) | Edit makes a new File from an existing one by instruction, such as upscaling or animating a still, and leaves the source unchanged. | [Content Lead](/agents/marketing/content-lead) | [`File.edited`](/business/events/File.edited) | Two-way: `try`, `send`, `do` | | [File.generate](/business/nouns/file/generate) | Generate makes an image, video, speech or music File from a prompt and reference Files, and records how it was made. | [Content Lead](/agents/marketing/content-lead) | [`File.generated`](/business/events/File.generated) | Two-way: `try`, `send`, `do` | | [File.create](/business/nouns/file/create) | Creates a File. Inherited from [Noun](/business/nouns/noun). | None. | `File.created` | Two-way: `try`, `send`, `do` | | [File.get](/business/nouns/file/get) | Returns one File by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [File.list](/business/nouns/file/list) | Returns Files, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [File.update](/business/nouns/file/update) | Changes the given properties of a File. Inherited from [Noun](/business/nouns/noun). | None. | `File.updated` | Two-way: `try`, `send`, `do` | | [File.delete](/business/nouns/file/delete) | Deletes a File; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `File.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `File.create` | Yes | Yes | Yes | No | | `File.get` | Yes | Yes | Yes | Yes | | `File.list` | Yes | Yes | Yes | Yes | | `File.update` | Yes | Yes | Yes | No | | `File.delete` | Yes | Yes | Yes | No | | `File.edit` | Yes | Yes | Yes | No | | `File.generate` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Generate the latest file. ``` **API** ```bash curl -X POST https://api.sb/patentpad.com/files/generate \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"kind":"image","prompt":"Example prompt"}' ``` ```json { "api": "https://api.sb/patentpad.com", "file": { "$id": "https://api.sb/patentpad.com/files/file_1", "$type": "File", "contentType": "Example content type", "size": 1 }, "action": { "$id": "https://api.sb/patentpad.com/actions/action_1", "operation": "File.generate", "status": "done" }, "links": { "self": "https://api.sb/patentpad.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const file = await $.File.generate({ kind: 'image', prompt: 'Example prompt' }) ``` **CLI** ```bash npx startup-builder do File.generate --json '{"kind":"image","prompt":"Example prompt"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.File.generate({ kind: 'image', prompt: 'Example prompt' })" } } ``` ## Example A recruiting agency uploads `candidates.csv`: 40,000 rows, 18 MB. The File holds those bytes, and the import report it gets back is a second File, the PDF export of a [Document](/business/nouns/document). # evaluate URL: /business/nouns/flag/evaluate · Id: `verb:Flag.evaluate` · Call: `await $.Flag.evaluate({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Evaluate returns the Variant a Flag assigns one unit, the same one every time, and records the Exposure with every option and its propensity. Evaluate returns the [Variant](/business/nouns/variant) a [Flag](/business/nouns/flag) assigns one unit, the same one every time, and records the [Exposure](/business/nouns/exposure) with every option and its propensity. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `flag` | [Flag](/business/nouns/flag) | Yes | The Flag to evaluate, by key. | | `unit` | `string` | Yes | The id of the Visitor, Customer, Contact, Conversation or request being assigned. | | `default` | `string` | No | The Variant key returned when the Flag is off or the value may not be varied. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `variant` | [Variant](/business/nouns/variant) | Yes | The Variant assigned to the unit. | | `exposure` | [Exposure](/business/nouns/exposure) | No | The Exposure recorded; none in Mode try. | ## Effects - Emits [`Flag.evaluated`](/business/events/Flag.evaluated). - Records no Exposure in Mode try, so a preview never counts toward a Readout. - Returns the default, and records why, when the value is on the never-randomized list. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Flag.evaluate](/business/nouns/flag/evaluate) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Evaluate the latest flag. ``` **API** ```bash curl -X POST https://api.sb/routewise.dev/flags/flag_1/evaluate \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"unit":"Example unit"}' ``` ```json { "api": "https://api.sb/routewise.dev", "variant": { "$id": "https://api.sb/routewise.dev/variants/variant_1", "$type": "Variant", "key": "Example key", "value": {} }, "exposure": { "$id": "https://api.sb/routewise.dev/exposures/exposure_1", "$type": "Exposure", "unit": "Example unit", "options": {}, "propensity": 1, "at": "2026-10-22T12:00:00Z" }, "action": { "$id": "https://api.sb/routewise.dev/actions/action_1", "operation": "Flag.evaluate", "status": "done" }, "links": { "self": "https://api.sb/routewise.dev/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { variant, exposure } = await $.Flag.evaluate({ flag: 'flag_1', unit: 'Example unit' }) ``` **CLI** ```bash npx startup-builder do Flag.evaluate --json '{"flag":"flag_1","unit":"Example unit"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Flag.evaluate({ flag: 'flag_1', unit: 'Example unit' })" } } ``` # Flag URL: /business/nouns/flag · Id: `noun:flag` > A Flag is a switch, evaluated per Visitor, Customer, or request, that selects which copy or behavior they get. A Flag is a switch, evaluated per [Visitor](/business/nouns/visitor), [Customer](/business/nouns/customer), or request, that selects which copy or behavior they get. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `key` | `string` | Yes | The name code reads. | | `rules` | `json` | No | Who gets which value, including percentage splits. | ## Object ```json { "$id": "https://api.sb/quietcopy.com/flags/flag_1", "$type": "Flag", "key": "new-checkout", "rules": {} } ``` ## Relationships - A Flag **assigns** many [Experiments](/business/nouns/experiment): Flags split units across an [Experiment](/business/nouns/experiment)’s [Variants](/business/nouns/variant) and log each assignment with its propensity. `assigns`, inverse [`assignsWith`](/business/nouns/experiment#rel-assigns-with). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Flag.evaluate](/business/nouns/flag/evaluate) | Evaluate returns the Variant a Flag assigns one unit, the same one every time, and records the Exposure with every option and its propensity. | [Agent](/business/nouns/agent) | [`Flag.evaluated`](/business/events/Flag.evaluated) | None. | | [Flag.create](/business/nouns/flag/create) | Creates a Flag. Inherited from [Noun](/business/nouns/noun). | None. | `Flag.created` | Two-way: `try`, `send`, `do` | | [Flag.get](/business/nouns/flag/get) | Returns one Flag by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Flag.list](/business/nouns/flag/list) | Returns Flags, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Flag.update](/business/nouns/flag/update) | Changes the given properties of a Flag. Inherited from [Noun](/business/nouns/noun). | None. | `Flag.updated` | Two-way: `try`, `send`, `do` | | [Flag.delete](/business/nouns/flag/delete) | Deletes a Flag; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Flag.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Flag.create` | Yes | Yes | Yes | No | | `Flag.get` | Yes | Yes | Yes | Yes | | `Flag.list` | Yes | Yes | Yes | Yes | | `Flag.update` | Yes | Yes | Yes | No | | `Flag.delete` | Yes | Yes | Yes | No | | `Flag.evaluate` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Evaluate the latest flag. ``` **API** ```bash curl -X POST https://api.sb/routewise.dev/flags/flag_1/evaluate \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"unit":"Example unit"}' ``` ```json { "api": "https://api.sb/routewise.dev", "variant": { "$id": "https://api.sb/routewise.dev/variants/variant_1", "$type": "Variant", "key": "Example key", "value": {} }, "exposure": { "$id": "https://api.sb/routewise.dev/exposures/exposure_1", "$type": "Exposure", "unit": "Example unit", "options": {}, "propensity": 1, "at": "2026-10-22T12:00:00Z" }, "action": { "$id": "https://api.sb/routewise.dev/actions/action_1", "operation": "Flag.evaluate", "status": "done" }, "links": { "self": "https://api.sb/routewise.dev/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { variant, exposure } = await $.Flag.evaluate({ flag: 'flag_1', unit: 'Example unit' }) ``` **CLI** ```bash npx startup-builder do Flag.evaluate --json '{"flag":"flag_1","unit":"Example unit"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Flag.evaluate({ flag: 'flag_1', unit: 'Example unit' })" } } ``` ## Example The Flag `pricing-page-v2` shows the new pricing [Page](/business/nouns/page) to 50% of Visitors and the prior Page to the rest. # Flow URL: /business/nouns/flow · Id: `noun:flow` > A Flow is an ordered path through an App’s Dashboards that takes one Persona from first run to an Offer’s activation Event. A Flow is an ordered path through an [App](/business/nouns/app)’s [Dashboards](/business/nouns/dashboard) that takes one [Persona](/business/nouns/persona) from first run to an [Offer](/business/nouns/offer)’s activation [Event](/business/nouns/event). ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `persona` | [Persona](/business/nouns/persona) | Yes | The Persona it guides; its Role decides which Verbs each step offers. | | `offer` | [Offer](/business/nouns/offer) | Yes | The Offer whose activation Event ends the Flow; time to value reads from first step to that Event. | | `steps` | list of [Dashboard](/business/nouns/dashboard) | Yes | The Dashboards in order, first run first, each ending in the Verb that opens the next. | ## Object ```json { "$id": "https://api.sb/petpantry.shop/flows/flow_1", "$type": "Flow", "persona": "persona_1", "offer": "offer_1", "steps": [ "dashboard_1" ] } ``` ## Relationships - A Flow **has** one [App](/business/nouns/app): the Flows an [App](/business/nouns/app) runs on first sign-in, one per [Persona](/business/nouns/persona) and [Offer](/business/nouns/offer), each ending at the activation [Event](/business/nouns/event). `app`, inverse [`guides`](/business/nouns/app#rel-guides). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Flow.create](/business/nouns/flow/create) | Creates a Flow. Inherited from [Noun](/business/nouns/noun). | None. | `Flow.created` | Two-way: `try`, `send`, `do` | | [Flow.get](/business/nouns/flow/get) | Returns one Flow by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Flow.list](/business/nouns/flow/list) | Returns Flows, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Flow.update](/business/nouns/flow/update) | Changes the given properties of a Flow. Inherited from [Noun](/business/nouns/noun). | None. | `Flow.updated` | Two-way: `try`, `send`, `do` | | [Flow.delete](/business/nouns/flow/delete) | Deletes a Flow; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Flow.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Flow.create` | Yes | Yes | Yes | No | | `Flow.get` | Yes | Yes | Yes | Yes | | `Flow.list` | Yes | Yes | Yes | Yes | | `Flow.update` | Yes | Yes | Yes | No | | `Flow.delete` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Add a flow to Kiln Bakery with a persona and an offer and a dashboard. ``` **API** ```bash curl -X POST https://api.sb/kilnbakery.com/flows \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"persona":"persona_1","offer":"offer_1","steps":["dashboard_1"]}' ``` ```json { "api": "https://api.sb/kilnbakery.com", "flow": { "$id": "https://api.sb/kilnbakery.com/flows/flow_1", "$type": "Flow", "persona": "persona_1", "offer": "offer_1", "steps": [ "dashboard_1" ] }, "action": { "$id": "https://api.sb/kilnbakery.com/actions/action_1", "operation": "Flow.create", "status": "done" }, "links": { "self": "https://api.sb/kilnbakery.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const flow = await $.Flow.create({ persona: 'persona_1', offer: 'offer_1', steps: ['dashboard_1'] }) ``` **CLI** ```bash npx startup-builder do Flow.create --json '{"persona":"persona_1","offer":"offer_1","steps":["dashboard_1"]}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Flow.create({ persona: 'persona_1', offer: 'offer_1', steps: ['dashboard_1'] })" } } ``` ## Example The buyer Flow on `stitchly.co` has three steps: describe a garment, pick a tailor, pay for the first [Order](/business/nouns/order). It ends at `Customer.activated`, and time to value is measured across those three steps. # Forecast URL: /business/nouns/forecast · Id: `noun:forecast` > A Forecast is a dated week-by-week projection of a Startup’s cash, revenue and Cost, computed from its records, that sets its spend state. A Forecast is a dated week-by-week projection of a [Startup](/business/nouns/startup)’s cash, revenue and [Cost](/business/nouns/cost), computed from its records, that sets its spend state. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `asOf` | `datetime` | Yes | When the inputs were read. | | `runwayWeeks` | `number` | Yes | Weeks until cash reaches zero at the projected rates. | | `defaultAlive` | `boolean` | Yes | True when projected revenue covers projected Cost before cash runs out. | | `profitWeek` | `date` | No | The first week projected revenue covers fully loaded Cost. | | `spendState` | `string` | Yes | The spend state it sets: `free` when default alive, `tight` when default dead, `hold` under 13 weeks of runway. | ## Object ```json { "$id": "https://api.sb/patentpad.com/forecasts/forecast_1", "$type": "Forecast", "asOf": "2026-10-22T12:00:00Z", "runwayWeeks": 1, "defaultAlive": true, "profitWeek": "2026-10-22", "spendState": "free" } ``` ## Relationships - A Forecast **has** one [Startup](/business/nouns/startup): the default-alive check writes a Forecast every week and after every large money [Decision](/business/nouns/decision); the latest sets the spend state. `startup`, inverse [`forecasts`](/business/nouns/startup#rel-forecasts). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Forecast.create](/business/nouns/forecast/create) | Creates a Forecast. Inherited from [Noun](/business/nouns/noun). | None. | `Forecast.created` | Two-way: `try`, `send`, `do` | | [Forecast.get](/business/nouns/forecast/get) | Returns one Forecast by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Forecast.list](/business/nouns/forecast/list) | Returns Forecasts, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | A Forecast is kept forever and never edited: it has no `update` or `delete`. ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Forecast.create` | Yes | Yes | Yes | No | | `Forecast.get` | Yes | Yes | Yes | Yes | | `Forecast.list` | Yes | Yes | Yes | Yes | ## Call it **Ask** ```text Add a forecast to ShiftNote. ``` **API** ```bash curl -X POST https://api.sb/shiftnote.app/forecasts \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"asOf":"2026-10-22T12:00:00Z","runwayWeeks":1,"defaultAlive":true,"spendState":"free"}' ``` ```json { "api": "https://api.sb/shiftnote.app", "forecast": { "$id": "https://api.sb/shiftnote.app/forecasts/forecast_1", "$type": "Forecast", "asOf": "2026-10-22T12:00:00Z", "runwayWeeks": 1, "defaultAlive": true, "spendState": "free" }, "action": { "$id": "https://api.sb/shiftnote.app/actions/action_1", "operation": "Forecast.create", "status": "done" }, "links": { "self": "https://api.sb/shiftnote.app/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const forecast = await $.Forecast.create({ asOf: '2026-10-22T12:00:00Z', runwayWeeks: 1, defaultAlive: true, spendState: 'free' }) ``` **CLI** ```bash npx startup-builder do Forecast.create --json '{"asOf":"2026-10-22T12:00:00Z","runwayWeeks":1,"defaultAlive":true,"spendState":"free"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Forecast.create({ asOf: '2026-10-22T12:00:00Z', runwayWeeks: 1, defaultAlive: true, spendState: 'free' })" } } ``` ## Example A [Startup](/business/nouns/startup) with $180,000 in cash and $9,000 of weekly net burn gets a Forecast of 20 runway weeks. Revenue does not cover [Cost](/business/nouns/cost) in that window, so `defaultAlive` is false and the spend state is `tight`. # Form URL: /business/nouns/form · Id: `noun:form` > A Form is a set of fields someone fills in on a Site or in a Message, producing a Lead, Evidence, or a Thing. A Form is a set of fields someone fills in on a [Site](/business/nouns/site) or in a [Message](/business/nouns/message), producing a [Lead](/business/nouns/lead), [Evidence](/business/nouns/evidence), or a [Thing](/business/nouns/thing). ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `fields` | `json` | Yes | The fields and their types. | ## Object ```json { "$id": "https://api.sb/quietcopy.com/forms/form_1", "$type": "Form", "fields": {} } ``` ## Relationships - A Form **captures** many [Leads](/business/nouns/lead): each Form submission creates a [Lead](/business/nouns/lead). `captures`, inverse [`capturedBy`](/business/nouns/lead#rel-captured-by). - A Form **is embedded in** many [Pages](/business/nouns/page): Forms sit on [Pages](/business/nouns/page); one Form appears on many Pages. `embeddedIn`, inverse [`embeds`](/business/nouns/page#rel-embeds). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Form.create](/business/nouns/form/create) | Creates a Form. Inherited from [Noun](/business/nouns/noun). | None. | `Form.created` | Two-way: `try`, `send`, `do` | | [Form.get](/business/nouns/form/get) | Returns one Form by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Form.list](/business/nouns/form/list) | Returns Forms, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Form.update](/business/nouns/form/update) | Changes the given properties of a Form. Inherited from [Noun](/business/nouns/noun). | None. | `Form.updated` | Two-way: `try`, `send`, `do` | | [Form.delete](/business/nouns/form/delete) | Deletes a Form; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Form.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Form.create` | Yes | Yes | Yes | No | | `Form.get` | Yes | Yes | Yes | Yes | | `Form.list` | Yes | Yes | Yes | Yes | | `Form.update` | Yes | Yes | Yes | No | | `Form.delete` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Add a form to TutorLoop. ``` **API** ```bash curl -X POST https://api.sb/tutorloop.com/forms \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"fields":{}}' ``` ```json { "api": "https://api.sb/tutorloop.com", "form": { "$id": "https://api.sb/tutorloop.com/forms/form_1", "$type": "Form", "fields": {} }, "action": { "$id": "https://api.sb/tutorloop.com/actions/action_1", "operation": "Form.create", "status": "done" }, "links": { "self": "https://api.sb/tutorloop.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const form = await $.Form.create({ fields: {} }) ``` **CLI** ```bash npx startup-builder do Form.create --json '{"fields":{}}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Form.create({ fields: {} })" } } ``` ## Example The booking Form on a home-inspector directory asks for the address, the closing date, and a phone number. Each submission creates a [Lead](/business/nouns/lead) and offers it to three inspectors. # Function URL: /business/nouns/function · Id: `noun:function` > A Function is how a Verb executes, as code, a generative model, an Agent, or a Human, invisible to the caller. A Function is how a [Verb](/business/nouns/verb) executes, as code, a generative model, an [Agent](/business/nouns/agent), or a [Human](/business/nouns/human), invisible to the caller. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `kind` | `string` | Yes | One of `code`, `generative`, `agentic`, or `human`. | | `version` | `string` | No | The Version an Action runs, kept with the Action. | | `cascade` | `string[]` | No | Kinds tried in order when one declines, such as code, then a Human. | | `instructions` | `text` | No | For a generative or agentic Function, what it does and how. | | `model` | `string` | No | For a generative or agentic Function, the model it runs on. | | `tools` | list of [Verb](/business/nouns/verb) | No | For an agentic Function, the Verbs it may call; Permissions and Limits apply to each. | | `maxSteps` | `integer` | No | For an agentic Function, the most steps one Action may take. | | `budget` | `money` | No | The most one Action may spend; the Mandate’s Limits apply as well. | | `role` | [Role](/business/nouns/role) | No | For a human Function, the Role its Tasks go to. | | `form` | `json` | No | For a human Function, the form; generated from the Verb’s inputs and outputs when absent. | | `sla` | `string` | No | For a human Function, how long a Task may wait, as an ISO 8601 duration. | | `escalateTo` | [Role](/business/nouns/role) | No | For a human Function, the Role a Task moves to when the service level passes. | ## Object ```json { "$id": "https://api.sb/kilnbakery.com/functions/function_1", "$type": "Function", "kind": "code", "version": "Example version", "cascade": [ "Example cascade" ], "instructions": "Example instructions", "model": "Example model", "tools": [ "verb_1" ], "maxSteps": 1, "budget": { "amount": 9, "currency": "USD" }, "role": "role_1", "form": {}, "sla": "PT4H", "escalateTo": "role_1" } ``` ## Relationships - A Function **implements** one [Verb](/business/nouns/verb): a Function is how a [Verb](/business/nouns/verb) runs: code, a generative model, an [Agent](/business/nouns/agent) or a [Human](/business/nouns/human), and the caller never sees which. `implements`, inverse [`implementedBy`](/business/nouns/verb#rel-implemented-by). - A Function **uses** many [Secrets](/business/nouns/secret): a Function declares the [Secrets](/business/nouns/secret) it reads; deploying to `live` fails when one is missing there. `uses`, inverse [`usedBy`](/business/nouns/secret#rel-used-by). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Function.create](/business/nouns/function/create) | Creates a Function. Inherited from [Noun](/business/nouns/noun). | None. | `Function.created` | Two-way: `try`, `send`, `do` | | [Function.get](/business/nouns/function/get) | Returns one Function by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Function.list](/business/nouns/function/list) | Returns Functions, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Function.update](/business/nouns/function/update) | Changes the given properties of a Function. Inherited from [Noun](/business/nouns/noun). | None. | `Function.updated` | Two-way: `try`, `send`, `do` | | [Function.delete](/business/nouns/function/delete) | Deletes a Function; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Function.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Function.create` | Yes | Yes | Yes | No | | `Function.get` | Yes | Yes | Yes | Yes | | `Function.list` | Yes | Yes | Yes | Yes | | `Function.update` | Yes | Yes | Yes | No | | `Function.delete` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Add a function to PetPantry. ``` **API** ```bash curl -X POST https://api.sb/petpantry.shop/functions \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"kind":"code"}' ``` ```json { "api": "https://api.sb/petpantry.shop", "function": { "$id": "https://api.sb/petpantry.shop/functions/function_1", "$type": "Function", "kind": "code" }, "action": { "$id": "https://api.sb/petpantry.shop/actions/action_1", "operation": "Function.create", "status": "done" }, "links": { "self": "https://api.sb/petpantry.shop/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const result = await $.Function.create({ kind: 'code' }) ``` **CLI** ```bash npx startup-builder do Function.create --json '{"kind":"code"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Function.create({ kind: 'code' })" } } ``` ## Example At a tax-preparation service, `Return.draft` runs as an [Agent](/business/nouns/agent), `Return.check` runs as code, and `Return.sign` runs as a credentialed [Human](/business/nouns/human). The caller invokes all three the same way. # Funnel URL: /business/nouns/funnel · Id: `noun:funnel` > A Funnel is a designed path to an Offer: a landing Page, an opt-in that makes a Lead, a Sequence, then the Offer. A Funnel is a designed path to an [Offer](/business/nouns/offer): a landing [Page](/business/nouns/page), an opt-in that makes a [Lead](/business/nouns/lead), a [Sequence](/business/nouns/sequence), then the Offer. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `steps` | `json` | Yes | The Pages, Forms, and Sequences in order. | ## Object ```json { "$id": "https://api.sb/kilnbakery.com/funnels/funnel_1", "$type": "Funnel", "steps": {} } ``` ## Relationships - A Funnel **leads to** one [Offer](/business/nouns/offer): each Funnel’s path ends at one [Offer](/business/nouns/offer), after its landing [Page](/business/nouns/page), opt-in and [Sequence](/business/nouns/sequence). `leadsTo`, inverse [`funnels`](/business/nouns/offer#rel-funnels). - A Funnel **nurtures with** many [Sequences](/business/nouns/sequence): a Funnel follows up with each new [Lead](/business/nouns/lead) through [Sequences](/business/nouns/sequence) after the opt-in. `nurturesWith`, inverse [`nurtures`](/business/nouns/sequence#rel-nurtures). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Funnel.create](/business/nouns/funnel/create) | Creates a Funnel. Inherited from [Noun](/business/nouns/noun). | None. | `Funnel.created` | Two-way: `try`, `send`, `do` | | [Funnel.get](/business/nouns/funnel/get) | Returns one Funnel by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Funnel.list](/business/nouns/funnel/list) | Returns Funnels, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Funnel.update](/business/nouns/funnel/update) | Changes the given properties of a Funnel. Inherited from [Noun](/business/nouns/noun). | None. | `Funnel.updated` | Two-way: `try`, `send`, `do` | | [Funnel.delete](/business/nouns/funnel/delete) | Deletes a Funnel; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Funnel.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Funnel.create` | Yes | Yes | Yes | No | | `Funnel.get` | Yes | Yes | Yes | Yes | | `Funnel.list` | Yes | Yes | Yes | Yes | | `Funnel.update` | Yes | Yes | Yes | No | | `Funnel.delete` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Add a funnel to PetPantry. ``` **API** ```bash curl -X POST https://api.sb/petpantry.shop/funnels \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"steps":{}}' ``` ```json { "api": "https://api.sb/petpantry.shop", "funnel": { "$id": "https://api.sb/petpantry.shop/funnels/funnel_1", "$type": "Funnel", "steps": {} }, "action": { "$id": "https://api.sb/petpantry.shop/actions/action_1", "operation": "Funnel.create", "status": "done" }, "links": { "self": "https://api.sb/petpantry.shop/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const funnel = await $.Funnel.create({ steps: {} }) ``` **CLI** ```bash npx startup-builder do Funnel.create --json '{"steps":{}}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Funnel.create({ steps: {} })" } } ``` ## Example A directory of wedding photographers runs a Funnel. A landing [Page](/business/nouns/page) offers a free listing audit that captures a [Lead](/business/nouns/lead), four emails follow in a [Sequence](/business/nouns/sequence), and then comes the $15 Offer. # Gathering URL: /business/nouns/gathering · Id: `noun:gathering` > A Gathering is a scheduled session many people attend at once, such as a webinar, a workshop, or a launch call, hosted by a Startup. A Gathering is a scheduled session many people attend at once, such as a webinar, a workshop, or a launch call, hosted by a [Startup](/business/nouns/startup). ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `title` | `string` | Yes | What the Gathering is called on its Page and invitations. | | `at` | `datetime` | Yes | When it starts. | | `capacity` | `integer` | No | The most Registrations it admits before new ones join the waitlist. | | `recording` | `url` | No | Where the replay lives once it ends. | ## Object ```json { "$id": "https://api.sb/shiftnote.app/gatherings/gathering_1", "$type": "Gathering", "title": "Clinic schedule", "at": "2026-10-22T12:00:00Z", "capacity": 1, "recording": "https://shiftnote.app" } ``` ## Relationships - A Gathering **admits** many [Registrations](/business/nouns/registration): a Gathering admits [Registrations](/business/nouns/registration) up to its capacity, then waitlists the rest. `admits`, inverse [`gathering`](/business/nouns/registration#rel-gathering). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Gathering.register](/business/nouns/gathering/register) | Register gives a Contact a place at a Gathering, or a waitlist place when the Gathering is full. | [Marketing Lead](/agents/marketing/marketing-lead) | [`Gathering.registered`](/business/events/Gathering.registered) | Two-way: `try`, `send`, `do` | | [Gathering.create](/business/nouns/gathering/create) | Creates a Gathering. Inherited from [Noun](/business/nouns/noun). | None. | `Gathering.created` | Two-way: `try`, `send`, `do` | | [Gathering.get](/business/nouns/gathering/get) | Returns one Gathering by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Gathering.list](/business/nouns/gathering/list) | Returns Gatherings, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Gathering.update](/business/nouns/gathering/update) | Changes the given properties of a Gathering. Inherited from [Noun](/business/nouns/noun). | None. | `Gathering.updated` | Two-way: `try`, `send`, `do` | | [Gathering.delete](/business/nouns/gathering/delete) | Deletes a Gathering; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Gathering.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Gathering.create` | Yes | Yes | Yes | No | | `Gathering.get` | Yes | Yes | Yes | Yes | | `Gathering.list` | Yes | Yes | Yes | Yes | | `Gathering.update` | Yes | Yes | Yes | No | | `Gathering.delete` | Yes | Yes | Yes | No | | `Gathering.register` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Register the latest gathering with a contact. ``` **API** ```bash curl -X POST https://api.sb/kilnbakery.com/gatherings/gathering_1/register \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"contact":"contact_1"}' ``` ```json { "api": "https://api.sb/kilnbakery.com", "registration": { "$id": "https://api.sb/kilnbakery.com/registrations/registration_1", "$type": "Registration", "status": "invited" }, "gathering": { "$id": "https://api.sb/kilnbakery.com/gatherings/gathering_1", "$type": "Gathering", "title": "Saturday sourdough", "at": "2026-10-22T12:00:00Z" }, "action": { "$id": "https://api.sb/kilnbakery.com/actions/action_1", "operation": "Gathering.register", "status": "done" }, "links": { "self": "https://api.sb/kilnbakery.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { registration, gathering } = await $.Gathering.register({ gathering: 'gathering_1', contact: 'contact_1' }) ``` **CLI** ```bash npx startup-builder do Gathering.register --json '{"gathering":"gathering_1","contact":"contact_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Gathering.register({ gathering: 'gathering_1', contact: 'contact_1' })" } } ``` ## Example A bookkeeping app hosts a 45-minute workshop on closing the month, with capacity for 300. The 301st [Registration](/business/nouns/registration) joins the waitlist, and the replay link goes to every registrant the next morning. # register URL: /business/nouns/gathering/register · Id: `verb:Gathering.register` · Call: `await $.Gathering.register({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Register gives a Contact a place at a Gathering, or a waitlist place when the Gathering is full. Register gives a [Contact](/business/nouns/contact) a place at a [Gathering](/business/nouns/gathering), or a waitlist place when the Gathering is full. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `gathering` | [Gathering](/business/nouns/gathering) | Yes | The Gathering. | | `contact` | [Contact](/business/nouns/contact) | Yes | Who takes the place. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `registration` | [Registration](/business/nouns/registration) | Yes | The Registration, `registered` or `waitlisted`. | | `gathering` | [Gathering](/business/nouns/gathering) | Yes | The Gathering with its registered count. | ## Effects - Emits [`Gathering.registered`](/business/events/Gathering.registered). - Performed by the [Marketing Lead](/agents/marketing/marketing-lead). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Makes the Contact a Lead when it has no open Lead, with the Gathering’s Acquisition. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Gathering.register](/business/nouns/gathering/register) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Medium: two-way, visible | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | 1 business hour, in which a watcher can pause, redirect or cancel it; then it runs. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Register the latest gathering with a contact. ``` **API** ```bash curl -X POST https://api.sb/kilnbakery.com/gatherings/gathering_1/register \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"contact":"contact_1"}' ``` ```json { "api": "https://api.sb/kilnbakery.com", "registration": { "$id": "https://api.sb/kilnbakery.com/registrations/registration_1", "$type": "Registration", "status": "invited" }, "gathering": { "$id": "https://api.sb/kilnbakery.com/gatherings/gathering_1", "$type": "Gathering", "title": "Saturday sourdough", "at": "2026-10-22T12:00:00Z" }, "action": { "$id": "https://api.sb/kilnbakery.com/actions/action_1", "operation": "Gathering.register", "status": "done" }, "links": { "self": "https://api.sb/kilnbakery.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { registration, gathering } = await $.Gathering.register({ gathering: 'gathering_1', contact: 'contact_1' }) ``` **CLI** ```bash npx startup-builder do Gathering.register --json '{"gathering":"gathering_1","contact":"contact_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Gathering.register({ gathering: 'gathering_1', contact: 'contact_1' })" } } ``` # Goal URL: /business/nouns/goal · Id: `noun:goal` > A Goal is what a Thing is trying to achieve: an objective with one or more Key Results. A Goal is what a [Thing](/business/nouns/thing) is trying to achieve: an objective with one or more [Key Results](/business/nouns/key-result). Every [Startup](/business/nouns/startup) holds one Goal it must reach: its [Minimum Success Criteria](/business/nouns/minimum-success-criteria). ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `objective` | `text` | Yes | The qualitative outcome. | | `horizon` | `string` | No | One of `day`, `week`, `quarter`, `year`, or `three-years`. | ## Object ```json { "$id": "https://api.sb/shiftnote.app/goals/goal_1", "$type": "Goal", "objective": "Example objective", "horizon": "day" } ``` ## Relationships - A Goal **is advanced by** many [Campaigns](/business/nouns/campaign): a [Campaign](/business/nouns/campaign) spends its budget and window toward one Goal. `advancedBy`, inverse [`advances`](/business/nouns/campaign#rel-advances). - A Goal **is held by** one [Thing](/business/nouns/thing): every [Thing](/business/nouns/thing) pursues Goals, such as a [Startup](/business/nouns/startup)’s quarterly objective or a [Team](/business/nouns/team)’s weekly target. `heldBy`, inverse [`aimsFor`](/business/nouns/thing#rel-aims-for). - A Goal **has** many [Key Results](/business/nouns/key-result): a Goal is met when its [Key Results](/business/nouns/key-result) reach their targets. `keyResults`, inverse [`measures`](/business/nouns/key-result#rel-measures). - A Goal **has** many [Projects](/business/nouns/project): a [Project](/business/nouns/project)’s work serves one Goal. `projects`, inverse [`advances`](/business/nouns/project#rel-advances). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Goal.create](/business/nouns/goal/create) | Creates a Goal. Inherited from [Noun](/business/nouns/noun). | None. | `Goal.created` | Two-way: `try`, `send`, `do` | | [Goal.get](/business/nouns/goal/get) | Returns one Goal by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Goal.list](/business/nouns/goal/list) | Returns Goals, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Goal.update](/business/nouns/goal/update) | Changes the given properties of a Goal. Inherited from [Noun](/business/nouns/noun). | None. | `Goal.updated` | Two-way: `try`, `send`, `do` | | [Goal.delete](/business/nouns/goal/delete) | Deletes a Goal; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Goal.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Goal.create` | Yes | Yes | Yes | No | | `Goal.get` | Yes | Yes | Yes | Yes | | `Goal.list` | Yes | Yes | Yes | Yes | | `Goal.update` | Yes | Yes | Yes | No | | `Goal.delete` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Add a goal to RouteWise. ``` **API** ```bash curl -X POST https://api.sb/routewise.dev/goals \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"objective":"Example objective"}' ``` ```json { "api": "https://api.sb/routewise.dev", "goal": { "$id": "https://api.sb/routewise.dev/goals/goal_1", "$type": "Goal", "objective": "Example objective" }, "action": { "$id": "https://api.sb/routewise.dev/actions/action_1", "operation": "Goal.create", "status": "done" }, "links": { "self": "https://api.sb/routewise.dev/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const goal = await $.Goal.create({ objective: 'Example objective' }) ``` **CLI** ```bash npx startup-builder do Goal.create --json '{"objective":"Example objective"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Goal.create({ objective: 'Example objective' })" } } ``` ## Example A clinic-reminder [SaaS](/products/templates/saas) holds a Goal with the `objective` "cut no-shows for 200 clinics" and `horizon: year`. Its one Key Result moves paid clinics from 35 to 200. # Guard URL: /business/nouns/guard · Id: `noun:guard` > A Guard is a check every outbound Message and publish passes, from code rules to model review to a Human for high stakes. A Guard is a check every outbound [Message](/business/nouns/message) and publish passes, from code rules to model review to a [Human](/business/nouns/human) for high stakes. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `tier` | `string` | Yes | One of `code`, `model`, `reviewer`, or `human`. | | `checks` | `string` | No | What it refuses; a `claim` Guard checks a stated term or promise against the record that backs it. Never randomized. | ## Object ```json { "$id": "https://api.sb/shiftnote.app/guards/guard_1", "$type": "Guard", "tier": "code", "checks": "tone" } ``` ## Relationships - A Guard **screens** many [Messages](/business/nouns/message): Guards check every outbound [Message](/business/nouns/message) before it goes out. `screens`, inverse [`screenedBy`](/business/nouns/message#rel-screened-by). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Guard.create](/business/nouns/guard/create) | Creates a Guard. Inherited from [Noun](/business/nouns/noun). | None. | `Guard.created` | Two-way: `try`, `send`, `do` | | [Guard.get](/business/nouns/guard/get) | Returns one Guard by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Guard.list](/business/nouns/guard/list) | Returns Guards, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Guard.update](/business/nouns/guard/update) | Changes the given properties of a Guard. Inherited from [Noun](/business/nouns/noun). | None. | `Guard.updated` | Two-way: `try`, `send`, `do` | | [Guard.delete](/business/nouns/guard/delete) | Deletes a Guard; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Guard.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Guard.create` | Yes | Yes | No | No | | `Guard.get` | Yes | Yes | Yes | Yes | | `Guard.list` | Yes | Yes | Yes | Yes | | `Guard.update` | Yes | Yes | No | No | | `Guard.delete` | Yes | Yes | No | No | ## Call it **Ask** ```text Add a guard to RouteWise. ``` **API** ```bash curl -X POST https://api.sb/routewise.dev/guards \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"tier":"code"}' ``` ```json { "api": "https://api.sb/routewise.dev", "guard": { "$id": "https://api.sb/routewise.dev/guards/guard_1", "$type": "Guard", "tier": "code" }, "action": { "$id": "https://api.sb/routewise.dev/actions/action_1", "operation": "Guard.create", "status": "done" }, "links": { "self": "https://api.sb/routewise.dev/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const guard = await $.Guard.create({ tier: 'code' }) ``` **CLI** ```bash npx startup-builder do Guard.create --json '{"tier":"code"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Guard.create({ tier: 'code' })" } } ``` ## Example A Guard blocks a sales email that promises "guaranteed 100% accuracy," because the [Offer](/business/nouns/offer) warrants 99.5%. The [Agent](/business/nouns/agent) rewrites it before it sends. # connect URL: /business/nouns/handle/connect · Id: `verb:Handle.connect` · Call: `await $.Handle.connect({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Connect binds a Handle to the Integration credential it publishes through, once the platform confirms the account. Connect binds a [Handle](/business/nouns/handle) to the [Integration](/business/nouns/integration) credential it publishes through, once the platform confirms the account. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `handle` | [Handle](/business/nouns/handle) | Yes | The Handle. | | `integration` | [Integration](/business/nouns/integration) | Yes | The Integration credential. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `handle` | [Handle](/business/nouns/handle) | Yes | The connected Handle. | ## Effects - Emits [`Handle.connected`](/business/events/Handle.connected). - Performed by the [Content Lead](/agents/marketing/content-lead). - Two-way: it runs at once, in the `try`, `send` and `do` modes. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Handle.connect](/business/nouns/handle/connect) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Medium: two-way, visible | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | 1 business hour, in which a watcher can pause, redirect or cancel it; then it runs. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Connect the latest handle with an integration. ``` **API** ```bash curl -X POST https://api.sb/tutorloop.com/handles/handle_1/connect \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"integration":"integration_1"}' ``` ```json { "api": "https://api.sb/tutorloop.com", "handle": { "$id": "https://api.sb/tutorloop.com/handles/handle_1", "$type": "Handle", "venue": "Example venue", "name": "TutorLoop" }, "action": { "$id": "https://api.sb/tutorloop.com/actions/action_1", "operation": "Handle.connect", "status": "done" }, "links": { "self": "https://api.sb/tutorloop.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const handle = await $.Handle.connect({ handle: 'handle_1', integration: 'integration_1' }) ``` **CLI** ```bash npx startup-builder do Handle.connect --json '{"handle":"handle_1","integration":"integration_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Handle.connect({ handle: 'handle_1', integration: 'integration_1' })" } } ``` # Handle URL: /business/nouns/handle · Id: `noun:handle` > A Handle is an account or name a Startup or Brand holds on an outside platform, bound to an Integration credential. A Handle is an account or name a [Startup](/business/nouns/startup) or [Brand](/business/nouns/brand) holds on an outside platform, bound to an [Integration](/business/nouns/integration) credential. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `venue` | `string` | Yes | The venue it lives on, by id. | | `name` | `string` | Yes | The name as the platform shows it, such as `@example`. | | `shared` | `boolean` | No | True for a Studio account shared across sibling Startups; every Post names the Startup it speaks for. | | `agent` | `boolean` | No | True when an Agent runs it; its bio says so. | | `integration` | [Integration](/business/nouns/integration) | No | The Integration credential it publishes through. | ## Object ```json { "$id": "https://api.sb/tutorloop.com/handles/handle_1", "$type": "Handle", "venue": "Example venue", "name": "TutorLoop", "shared": true, "agent": true, "integration": "integration_1" } ``` ## Relationships - A Handle **publishes** many [Posts](/business/nouns/post): every [Post](/business/nouns/post) goes out from one Handle, so its reach and replies count toward that Handle. `publishes`, inverse [`handle`](/business/nouns/post#rel-handle). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Handle.connect](/business/nouns/handle/connect) | Connect binds a Handle to the Integration credential it publishes through, once the platform confirms the account. | [Content Lead](/agents/marketing/content-lead) | [`Handle.connected`](/business/events/Handle.connected) | Two-way: `try`, `send`, `do` | | [Handle.create](/business/nouns/handle/create) | Creates a Handle. Inherited from [Noun](/business/nouns/noun). | None. | `Handle.created` | Two-way: `try`, `send`, `do` | | [Handle.get](/business/nouns/handle/get) | Returns one Handle by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Handle.list](/business/nouns/handle/list) | Returns Handles, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Handle.update](/business/nouns/handle/update) | Changes the given properties of a Handle. Inherited from [Noun](/business/nouns/noun). | None. | `Handle.updated` | Two-way: `try`, `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Handle.create` | Yes | Yes | Yes | No | | `Handle.get` | Yes | Yes | Yes | Yes | | `Handle.list` | Yes | Yes | Yes | Yes | | `Handle.update` | Yes | Yes | Yes | No | | `Handle.connect` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Connect the latest handle with an integration. ``` **API** ```bash curl -X POST https://api.sb/tutorloop.com/handles/handle_1/connect \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"integration":"integration_1"}' ``` ```json { "api": "https://api.sb/tutorloop.com", "handle": { "$id": "https://api.sb/tutorloop.com/handles/handle_1", "$type": "Handle", "venue": "Example venue", "name": "TutorLoop" }, "action": { "$id": "https://api.sb/tutorloop.com/actions/action_1", "operation": "Handle.connect", "status": "done" }, "links": { "self": "https://api.sb/tutorloop.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const handle = await $.Handle.connect({ handle: 'handle_1', integration: 'integration_1' }) ``` **CLI** ```bash npx startup-builder do Handle.connect --json '{"handle":"handle_1","integration":"integration_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Handle.connect({ handle: 'handle_1', integration: 'integration_1' })" } } ``` ## Example A recipe app holds the Handle `@weeknightplates` on two social venues, both bound to one [Integration](/business/nouns/integration). An [Agent](/business/nouns/agent) runs them, and each bio says so. # Holder URL: /business/nouns/holder · Id: `noun:holder` > A Holder is the Party that holds a Share or an Instrument on a Company’s cap table. A Holder is the [Party](/business/nouns/party) that holds a [Share](/business/nouns/share) or an [Instrument](/business/nouns/instrument) on a [Company](/business/nouns/company)’s cap table. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `party` | [Party](/business/nouns/party) | Yes | The person or entity behind the holding. | ## Object ```json { "$id": "https://api.sb/quietcopy.com/holders/holder_1", "$type": "Holder", "party": "party_1" } ``` ## Relationships - A Holder **has** many [Instruments](/business/nouns/instrument): each [Instrument](/business/nouns/instrument) belongs to one Holder, who sees it, its vesting and its documents. `instruments`, inverse [`heldBy`](/business/nouns/instrument#rel-held-by). - A Holder **has** many [Shares](/business/nouns/share): each [Share](/business/nouns/share) record belongs to one Holder; a transfer writes a new record for the new Holder. `shares`, inverse [`heldBy`](/business/nouns/share#rel-held-by). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Holder.create](/business/nouns/holder/create) | Creates a Holder. Inherited from [Noun](/business/nouns/noun). | None. | `Holder.created` | Two-way: `try`, `send`, `do` | | [Holder.get](/business/nouns/holder/get) | Returns one Holder by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Holder.list](/business/nouns/holder/list) | Returns Holders, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Holder.update](/business/nouns/holder/update) | Changes the given properties of a Holder. Inherited from [Noun](/business/nouns/noun). | None. | `Holder.updated` | Two-way: `try`, `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Holder.create` | Yes | Yes | Yes | No | | `Holder.get` | Yes | Yes | Yes | Yes | | `Holder.list` | Yes | Yes | Yes | Yes | | `Holder.update` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Add a holder to TutorLoop with a party. ``` **API** ```bash curl -X POST https://api.sb/tutorloop.com/holders \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"party":"party_1"}' ``` ```json { "api": "https://api.sb/tutorloop.com", "holder": { "$id": "https://api.sb/tutorloop.com/holders/holder_1", "$type": "Holder", "party": "party_1" }, "action": { "$id": "https://api.sb/tutorloop.com/actions/action_1", "operation": "Holder.create", "status": "done" }, "links": { "self": "https://api.sb/tutorloop.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const holder = await $.Holder.create({ party: 'party_1' }) ``` **CLI** ```bash npx startup-builder do Holder.create --json '{"party":"party_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Holder.create({ party: 'party_1' })" } } ``` ## Example A founder holds 4 million common [Shares](/business/nouns/share) and an option [Instrument](/business/nouns/instrument) in her [Company](/business/nouns/company). The cap table shows one Holder for her, with both holdings under it. # hold URL: /business/nouns/human/hold · Id: `verb:Human.hold` · Call: `await $.Human.hold({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Hold sets aside part of a supplying Human’s earned balance against an open Dispute or an Order inside its clearance period. Hold sets aside part of a supplying [Human](/business/nouns/human)’s earned balance against an open [Dispute](/business/nouns/dispute) or an [Order](/business/nouns/order) inside its clearance period. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `human` | [Human](/business/nouns/human) | Yes | The payee. | | `amount` | `money` | Yes | The amount to hold. | | `cause` | `string` | Yes | The Order or Dispute the hold cites. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `human` | [Human](/business/nouns/human) | Yes | The payee, with the held amount recorded. | ## Effects - Emits [`Human.held`](/business/events/Human.held). - Performed by the [Billing Specialist](/agents/finance/billing-specialist). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - `Human.remit` pays only the balance not held. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Human.hold](/business/nouns/human/hold) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Hold Tomas Berg. ``` **API** ```bash curl -X POST https://api.sb/kilnbakery.com/humans/human_1/hold \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"amount":{"amount":9,"currency":"USD"},"cause":"Example cause"}' ``` ```json { "api": "https://api.sb/kilnbakery.com", "human": { "$id": "https://api.sb/kilnbakery.com/humans/human_1", "$type": "Human", "name": "Tomas Berg", "email": "tomas@kilnbakery.com" }, "action": { "$id": "https://api.sb/kilnbakery.com/actions/action_1", "operation": "Human.hold", "status": "done" }, "links": { "self": "https://api.sb/kilnbakery.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const human = await $.Human.hold({ human: 'human_1', amount: { amount: 9, currency: 'USD' }, cause: 'Example cause' }) ``` **CLI** ```bash npx startup-builder do Human.hold --json '{"human":"human_1","amount":{"amount":9,"currency":"USD"},"cause":"Example cause"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Human.hold({ human: 'human_1', amount: { amount: 9, currency: 'USD' }, cause: 'Example cause' })" } } ``` # Human URL: /business/nouns/human · Id: `noun:human` > A Human is a Worker who is a person, acting on Tasks through Apps, Mailboxes, and Channels. A Human is a [Worker](/business/nouns/worker) who is a person, acting on [Tasks](/business/nouns/task) through [Apps](/business/nouns/app), [Mailboxes](/business/nouns/mailbox), and [Channels](/business/nouns/channel). ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `email` | `email` | Yes | The address the Human signs in with. |
Inherited from [Worker](/business/nouns/worker): 2 properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `name` | `string` | Yes | The name the Worker goes by in a Startup. | | `instructions` | `text` | No | How the Worker does its work. |
## Object ```json { "$id": "https://api.sb/ledgerlark.com/humans/human_1", "$type": "Human", "name": "LedgerLark", "instructions": "Example instructions", "email": "priya@ledgerlark.com" } ``` ## Relationships - A Human **is paid in** many [Pay Runs](/business/nouns/pay-run): a [Pay Run](/business/nouns/pay-run) pays the Humans the [Company](/business/nouns/company) employs; each employee appears in one run per pay period. `paidIn`, inverse [`pays`](/business/nouns/pay-run#rel-pays). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Risk.accept](/business/nouns/risk/accept) | Accept records an officer’s signed Decision to carry a Risk untreated until its next review. | [Founder](/agents/founding/founder) | [`Risk.accepted`](/business/events/Risk.accepted) | One-way: `send`, `do` | | [Action.attest](/business/nouns/action/attest) | Attest records a credentialed Human’s signed performance of a Reserved Act that an Action needs to finish. | [Legal Lead](/agents/legal/legal-lead) | [`Action.attested`](/business/events/Action.attested) | None. | | [Startup.claim](/business/nouns/startup/claim) | Claim binds a provisional Startup to a verified owner, which enables payments and every Verb that moves money. | [Human](/business/nouns/human) | [`Startup.claimed`](/business/events/Startup.claimed) | None. | | [Human.hold](/business/nouns/human/hold) | Hold sets aside part of a supplying Human’s earned balance against an open Dispute or an Order inside its clearance period. | [Billing Specialist](/agents/finance/billing-specialist) | [`Human.held`](/business/events/Human.held) | Two-way: `try`, `send`, `do` | | [Human.invite](/business/nouns/human/invite) | Invite asks a person to join a Startup in a named Role, sharing that Role’s work with its Agent. | [Recruiter](/agents/people/recruiter) | [`Human.invited`](/business/events/Human.invited) | None. | | [Human.onboard](/business/nouns/human/onboard) | Onboard admits a recruited Human to supply work once their identity, Credentials and payout details verify. | [Supply Manager](/agents/operations/supply-manager) | [`Human.onboarded`](/business/events/Human.onboarded) | None. | | [Startup.pivot](/business/nouns/startup/pivot) | Pivot records a Decision that moves a Live Startup back to Building under a new Founding Hypothesis version. | [Founder](/agents/founding/founder) | [`Startup.pivoted`](/business/events/Startup.pivoted) | One-way (customer): `send`, `do` | | [Human.recruit](/business/nouns/human/recruit) | Recruit invites a person to supply credentialed work to a Startup through its supply App. | [Supply Manager](/agents/operations/supply-manager) | [`Human.recruited`](/business/events/Human.recruited) | None. | | [Human.release](/business/nouns/human/release) | Release frees a held amount for payout once its Dispute closes or its clearance period ends. | [Billing Specialist](/agents/finance/billing-specialist) | [`Human.released`](/business/events/Human.released) | Two-way: `try`, `send`, `do` | | [Human.remit](/business/nouns/human/remit) | Remit pays a supplying Human’s earned balance to their bank account through the Startup’s payment account. | [Supply Manager](/agents/operations/supply-manager) | [`Human.remitted`](/business/events/Human.remitted) | One-way (money): `send`, `do` | | [Agreement.sign](/business/nouns/agreement/sign) | Sign executes an Agreement for one Party and records the signature, the signer and the time. | [Founder](/agents/founding/founder) | [`Agreement.signed`](/business/events/Agreement.signed) | One-way (money): `send`, `do` | | [Human.suspend](/business/nouns/human/suspend) | Suspend stops a supplying Human from taking new Tasks while a Credential lapses or a dispute is open. | [Supply Manager](/agents/operations/supply-manager) | [`Human.suspended`](/business/events/Human.suspended) | None. | | [Human.create](/business/nouns/human/create) | Creates a Human. Inherited from [Noun](/business/nouns/noun). | None. | `Human.created` | Two-way: `try`, `send`, `do` | | [Human.get](/business/nouns/human/get) | Returns one Human by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Human.list](/business/nouns/human/list) | Returns Humans, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Human.update](/business/nouns/human/update) | Changes the given properties of a Human. Inherited from [Noun](/business/nouns/noun). | None. | `Human.updated` | Two-way: `try`, `send`, `do` | | [Human.delete](/business/nouns/human/delete) | Deletes a Human; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Human.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Human.create` | Yes | Yes | Yes | No | | `Human.get` | Yes | Yes | Yes | Yes | | `Human.list` | Yes | Yes | Yes | Yes | | `Human.update` | Yes | Yes | Yes | No | | `Human.delete` | Yes | Yes | Yes | No | | `Human.hold` | Yes | Yes | Yes | No | | `Human.invite` | Yes | Yes | Yes | No | | `Human.onboard` | Yes | Yes | Yes | No | | `Human.recruit` | Yes | Yes | Yes | No | | `Human.release` | Yes | Yes | Yes | No | | `Human.remit` | Yes | No | No | No | | `Human.suspend` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Remit Lena Fischer. ``` **API** ```bash curl -X POST https://api.sb/petpantry.shop/humans/human_1/remit \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/petpantry.shop", "transaction": { "$id": "https://api.sb/petpantry.shop/transactions/transaction_1", "$type": "Transaction", "kind": "charge", "amount": { "amount": 54, "currency": "USD" } }, "human": { "$id": "https://api.sb/petpantry.shop/humans/human_1", "$type": "Human", "name": "Lena Fischer", "email": "lena@petpantry.shop" }, "action": { "$id": "https://api.sb/petpantry.shop/actions/action_1", "operation": "Human.remit", "status": "done" }, "links": { "self": "https://api.sb/petpantry.shop/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { transaction, human } = await $.Human.remit({ human: 'human_1' }) ``` **CLI** ```bash npx startup-builder do Human.remit --json '{"human":"human_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Human.remit({ human: 'human_1' })" } } ``` ## Example A certified court translator is a Human who fills a reviewer [Role](/business/nouns/role) at a translation marketplace. She works [Tasks](/business/nouns/task) in the App, and only she signs each certification. # invite URL: /business/nouns/human/invite · Id: `verb:Human.invite` · Call: `await $.Human.invite({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Invite asks a person to join a Startup in a named Role, sharing that Role’s work with its Agent. Invite asks a person to join a [Startup](/business/nouns/startup) in a named [Role](/business/nouns/role), sharing that Role’s work with its [Agent](/business/nouns/agent). ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `email` | `email` | Yes | Where the invitation goes. | | `role` | [Role](/business/nouns/role) | Yes | The Role offered. | | `access` | `string` | No | The Access Level the person holds in the app, apart from the Role: `admin`, `member` or `viewer`. Owner is never invited. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `human` | [Human](/business/nouns/human) | Yes | The invited Human. | ## Effects - Emits [`Human.invited`](/business/events/Human.invited). - Performed by the [Recruiter](/agents/people/recruiter). - Staffs the Role with the Human once they accept. - Grants the Access Level named in `access` once they accept. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The input does not match the schema of the operation. | [`invalid-input`](/code/api/errors/invalid-input) | Read the schema of the operation, then send every required field with the right type. | [Human.invite](/business/nouns/human/invite) | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Human.invite](/business/nouns/human/invite) | | The record changed since it was read, so the write would overwrite a newer version. | [`conflict`](/code/api/errors/conflict) | Read the record again, then retry the write against its current state. | [Human.invite](/business/nouns/human/invite) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Invite Lena Fischer with a role. ``` **API** ```bash curl -X POST https://api.sb/petpantry.shop/humans/invite \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"email":"lena@petpantry.shop","role":"role_1"}' ``` ```json { "api": "https://api.sb/petpantry.shop", "human": { "$id": "https://api.sb/petpantry.shop/humans/human_1", "$type": "Human", "name": "Lena Fischer", "email": "lena@petpantry.shop" }, "action": { "$id": "https://api.sb/petpantry.shop/actions/action_1", "operation": "Human.invite", "status": "done" }, "links": { "self": "https://api.sb/petpantry.shop/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const human = await $.Human.invite({ email: 'lena@petpantry.shop', role: 'role_1' }) ``` **CLI** ```bash npx startup-builder do Human.invite --json '{"email":"lena@petpantry.shop","role":"role_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Human.invite({ email: 'lena@petpantry.shop', role: 'role_1' })" } } ``` Guides that call it: [Invite my cofounder as CTO](/agents/invite-a-person-to-a-role), [Give a teammate access](/agents/give-a-teammate-access). # onboard URL: /business/nouns/human/onboard · Id: `verb:Human.onboard` · Call: `await $.Human.onboard({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Onboard admits a recruited Human to supply work once their identity, Credentials and payout details verify. Onboard admits a recruited [Human](/business/nouns/human) to supply work once their identity, [Credentials](/business/nouns/credential) and payout details verify. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `human` | [Human](/business/nouns/human) | Yes | The recruited Human. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `human` | [Human](/business/nouns/human) | Yes | The Human, able to take Tasks. | ## Effects - Emits [`Human.onboarded`](/business/events/Human.onboarded). - Performed by the [Supply Manager](/agents/operations/supply-manager). - Refuses the Action and names each missing check. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The input does not match the schema of the operation. | [`invalid-input`](/code/api/errors/invalid-input) | Read the schema of the operation, then send every required field with the right type. | [Human.onboard](/business/nouns/human/onboard) | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Human.onboard](/business/nouns/human/onboard) | | The record is not in a state that allows this Verb, so the call is refused. | [`refused`](/code/api/errors/refused) | Read the record, run the Verb that moves it to an allowed state, then retry. | [Human.onboard](/business/nouns/human/onboard) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Onboard Malik Owens. ``` **API** ```bash curl -X POST https://api.sb/tutorloop.com/humans/human_1/onboard \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/tutorloop.com", "human": { "$id": "https://api.sb/tutorloop.com/humans/human_1", "$type": "Human", "name": "Malik Owens", "email": "malik@tutorloop.com" }, "action": { "$id": "https://api.sb/tutorloop.com/actions/action_1", "operation": "Human.onboard", "status": "done" }, "links": { "self": "https://api.sb/tutorloop.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const human = await $.Human.onboard({ human: 'human_1' }) ``` **CLI** ```bash npx startup-builder do Human.onboard --json '{"human":"human_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Human.onboard({ human: 'human_1' })" } } ``` # recruit URL: /business/nouns/human/recruit · Id: `verb:Human.recruit` · Call: `await $.Human.recruit({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Recruit invites a person to supply credentialed work to a Startup through its supply App. Recruit invites a person to supply credentialed work to a [Startup](/business/nouns/startup) through its supply [App](/business/nouns/app). ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `email` | `email` | Yes | Where the invitation goes. | | `credential` | `string` | No | The Credential the work requires. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `human` | [Human](/business/nouns/human) | Yes | The recruited Human. | ## Effects - Emits [`Human.recruited`](/business/events/Human.recruited). - Performed by the [Supply Manager](/agents/operations/supply-manager). ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The input does not match the schema of the operation. | [`invalid-input`](/code/api/errors/invalid-input) | Read the schema of the operation, then send every required field with the right type. | [Human.recruit](/business/nouns/human/recruit) | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Human.recruit](/business/nouns/human/recruit) | | The record is not in a state that allows this Verb, so the call is refused. | [`refused`](/code/api/errors/refused) | Read the record, run the Verb that moves it to an allowed state, then retry. | [Human.recruit](/business/nouns/human/recruit) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Recruit Priya Natarajan. ``` **API** ```bash curl -X POST https://api.sb/ledgerlark.com/humans/recruit \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"email":"priya@ledgerlark.com"}' ``` ```json { "api": "https://api.sb/ledgerlark.com", "human": { "$id": "https://api.sb/ledgerlark.com/humans/human_1", "$type": "Human", "name": "Priya Natarajan", "email": "priya@ledgerlark.com" }, "action": { "$id": "https://api.sb/ledgerlark.com/actions/action_1", "operation": "Human.recruit", "status": "done" }, "links": { "self": "https://api.sb/ledgerlark.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const human = await $.Human.recruit({ email: 'priya@ledgerlark.com' }) ``` **CLI** ```bash npx startup-builder do Human.recruit --json '{"email":"priya@ledgerlark.com"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Human.recruit({ email: 'priya@ledgerlark.com' })" } } ``` # release URL: /business/nouns/human/release · Id: `verb:Human.release` · Call: `await $.Human.release({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Release frees a held amount for payout once its Dispute closes or its clearance period ends. Release frees a held amount for payout once its [Dispute](/business/nouns/dispute) closes or its clearance period ends. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `human` | [Human](/business/nouns/human) | Yes | The payee. | | `cause` | `string` | Yes | The Order or Dispute whose hold ends. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `human` | [Human](/business/nouns/human) | Yes | The payee, with the hold removed. | ## Effects - Emits [`Human.released`](/business/events/Human.released). - Performed by the [Billing Specialist](/agents/finance/billing-specialist). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - A lost Dispute releases nothing: the held amount returns to the Customer instead. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Human.release](/business/nouns/human/release) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Release Tomas Berg. ``` **API** ```bash curl -X POST https://api.sb/kilnbakery.com/humans/human_1/release \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"cause":"Example cause"}' ``` ```json { "api": "https://api.sb/kilnbakery.com", "human": { "$id": "https://api.sb/kilnbakery.com/humans/human_1", "$type": "Human", "name": "Tomas Berg", "email": "tomas@kilnbakery.com" }, "action": { "$id": "https://api.sb/kilnbakery.com/actions/action_1", "operation": "Human.release", "status": "done" }, "links": { "self": "https://api.sb/kilnbakery.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const human = await $.Human.release({ human: 'human_1', cause: 'Example cause' }) ``` **CLI** ```bash npx startup-builder do Human.release --json '{"human":"human_1","cause":"Example cause"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Human.release({ human: 'human_1', cause: 'Example cause' })" } } ``` # remit URL: /business/nouns/human/remit · Id: `verb:Human.remit` · Call: `await $.Human.remit({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Remit pays a supplying Human’s earned balance to their bank account through the Startup’s payment account. Remit pays a supplying [Human](/business/nouns/human)’s earned balance to their bank account through the [Startup](/business/nouns/startup)’s payment account. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `human` | [Human](/business/nouns/human) | Yes | The Human to pay. | | `amount` | `money` | No | The amount. Defaults to the full earned balance. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `transaction` | [Transaction](/business/nouns/transaction) | Yes | The payout Transaction. | | `human` | [Human](/business/nouns/human) | Yes | The Human paid, with the balance now zero. | ## Effects - Emits [`Human.remitted`](/business/events/Human.remitted). - Performed by the [Supply Manager](/agents/operations/supply-manager). - One-way (money): it waits out its delay window, and runs in the `send` and `do` modes. - Pays only for work its Customer confirmed. - Checks the payout Limit; above it, opens an Approval. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The operation is part of an Offer the caller has not accepted or paid for. | [`payment-required`](/code/api/errors/payment-required) | Accept the Offer named in the response, then retry the call. | [Offer.accept](/business/nouns/offer/accept) | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Human.remit](/business/nouns/human/remit) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Medium: one-way, bounded (money) | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | 1 business hour, in which a watcher can pause, redirect or cancel it; then it runs. | | Limit | The spend [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) or [Mandate](/business/nouns/mandate) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Remit Lena Fischer. ``` **API** ```bash curl -X POST https://api.sb/petpantry.shop/humans/human_1/remit \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/petpantry.shop", "transaction": { "$id": "https://api.sb/petpantry.shop/transactions/transaction_1", "$type": "Transaction", "kind": "charge", "amount": { "amount": 54, "currency": "USD" } }, "human": { "$id": "https://api.sb/petpantry.shop/humans/human_1", "$type": "Human", "name": "Lena Fischer", "email": "lena@petpantry.shop" }, "action": { "$id": "https://api.sb/petpantry.shop/actions/action_1", "operation": "Human.remit", "status": "done" }, "links": { "self": "https://api.sb/petpantry.shop/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { transaction, human } = await $.Human.remit({ human: 'human_1' }) ``` **CLI** ```bash npx startup-builder do Human.remit --json '{"human":"human_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Human.remit({ human: 'human_1' })" } } ``` # suspend URL: /business/nouns/human/suspend · Id: `verb:Human.suspend` · Call: `await $.Human.suspend({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Suspend stops a supplying Human from taking new Tasks while a Credential lapses or a dispute is open. Suspend stops a supplying [Human](/business/nouns/human) from taking new [Tasks](/business/nouns/task) while a [Credential](/business/nouns/credential) lapses or a dispute is open. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `human` | [Human](/business/nouns/human) | Yes | The Human to suspend. | | `reason` | `text` | Yes | Why the Human stops. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `human` | [Human](/business/nouns/human) | Yes | The suspended Human. | ## Effects - Emits [`Human.suspended`](/business/events/Human.suspended). - Performed by the [Supply Manager](/agents/operations/supply-manager). - Reassigns the Human’s open Tasks. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Human.suspend](/business/nouns/human/suspend) | | The record is not in a state that allows this Verb, so the call is refused. | [`refused`](/code/api/errors/refused) | Read the record, run the Verb that moves it to an allowed state, then retry. | [Human.suspend](/business/nouns/human/suspend) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Suspend Rosa Ibarra. ``` **API** ```bash curl -X POST https://api.sb/patentpad.com/humans/human_1/suspend \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"reason":"Example reason"}' ``` ```json { "api": "https://api.sb/patentpad.com", "human": { "$id": "https://api.sb/patentpad.com/humans/human_1", "$type": "Human", "name": "Rosa Ibarra", "email": "rosa@patentpad.com" }, "action": { "$id": "https://api.sb/patentpad.com/actions/action_1", "operation": "Human.suspend", "status": "done" }, "links": { "self": "https://api.sb/patentpad.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const human = await $.Human.suspend({ human: 'human_1', reason: 'Example reason' }) ``` **CLI** ```bash npx startup-builder do Human.suspend --json '{"human":"human_1","reason":"Example reason"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Human.suspend({ human: 'human_1', reason: 'Example reason' })" } } ``` # drop URL: /business/nouns/hypothesis/drop · Id: `verb:Hypothesis.drop` · Call: `await $.Hypothesis.drop({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Drop retires a Hypothesis from active work and keeps it, with its Evidence, on record. Drop retires a [Hypothesis](/business/nouns/hypothesis) from active work and keeps it, with its [Evidence](/business/nouns/evidence), on record. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `hypothesis` | [Hypothesis](/business/nouns/hypothesis) | Yes | The Hypothesis to retire. | | `reason` | `text` | Yes | Why it is dropped. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `hypothesis` | [Hypothesis](/business/nouns/hypothesis) | Yes | The dropped Hypothesis. | ## Effects - Emits [`Hypothesis.dropped`](/business/events/Hypothesis.dropped). - Performed by the [Strategist](/agents/founding/strategist). ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Hypothesis.drop](/business/nouns/hypothesis/drop) | | The record is not in a state that allows this Verb, so the call is refused. | [`refused`](/code/api/errors/refused) | Read the record, run the Verb that moves it to an allowed state, then retry. | [Hypothesis.drop](/business/nouns/hypothesis/drop) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Drop the latest hypothesis. ``` **API** ```bash curl -X POST https://api.sb/shiftnote.app/hypotheses/hypothesis_1/drop \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"reason":"Example reason"}' ``` ```json { "api": "https://api.sb/shiftnote.app", "hypothesis": { "$id": "https://api.sb/shiftnote.app/hypotheses/hypothesis_1", "$type": "Hypothesis", "statement": "Schedules shifts for small medical clinics.", "kind": "founding", "verdict": "Open", "version": 1 }, "action": { "$id": "https://api.sb/shiftnote.app/actions/action_1", "operation": "Hypothesis.drop", "status": "done" }, "links": { "self": "https://api.sb/shiftnote.app/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const hypothesis = await $.Hypothesis.drop({ hypothesis: 'hypothesis_1', reason: 'Example reason' }) ``` **CLI** ```bash npx startup-builder do Hypothesis.drop --json '{"hypothesis":"hypothesis_1","reason":"Example reason"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Hypothesis.drop({ hypothesis: 'hypothesis_1', reason: 'Example reason' })" } } ``` # Hypothesis URL: /business/nouns/hypothesis · Id: `noun:hypothesis` > A Hypothesis is a belief about a Startup stated so it can be proved wrong, with the Metric and threshold that settle it. A Hypothesis is a belief about a [Startup](/business/nouns/startup) stated so it can be proved wrong, with the [Metric](/business/nouns/metric) and threshold that settle it. [Experiments](/business/nouns/experiment) test it, and [Evidence](/business/nouns/evidence) grades it. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `statement` | `text` | Yes | The belief, in one sentence. | | `kind` | `string` | Yes | One of `founding`, the five slots (`customer`, `problem`, `approach`, `switch`, `differentiation`), or `loop`. | | `parent` | [Hypothesis](/business/nouns/hypothesis) | No | The Founding Hypothesis a slot Hypothesis belongs to. | | `verdict` | `string` | Yes | One of `Open`, `Testing`, `Supported`, or `Refuted`. | | `metric` | [Metric](/business/nouns/metric) | No | The Metric that settles it. | | `threshold` | `string` | No | The Metric value that settles it. | | `grade` | `string` | No | Computed: the strongest grade of its outside Evidence, `None` without any. | | `version` | `integer` | Yes | Each merged Change adds one; outputs cite it in their lineage. | ## Object ```json { "$id": "https://api.sb/tutorloop.com/hypotheses/hypothesis_1", "$type": "Hypothesis", "statement": "Matches high school students with math tutors.", "kind": "founding", "parent": "hypothesis_1", "verdict": "Open", "metric": "metric_1", "threshold": "Example threshold", "grade": "Example grade", "version": 1 } ``` ## Relationships - A Hypothesis **has** many pieces of [Evidence](/business/nouns/evidence): [Evidence](/business/nouns/evidence) supports or refutes Hypotheses; the strongest outside Evidence sets each Hypothesis grade. `evidence`, inverse [`bearsOn`](/business/nouns/evidence#rel-bears-on). - A Hypothesis **is a slot of** one [Hypothesis](/business/nouns/hypothesis): the five slot Hypotheses of a Founding Hypothesis, each with a [Metric](/business/nouns/metric) and a threshold. `slotOf`, inverse `slots`. - A Hypothesis’s **slots** are many [Hypotheses](/business/nouns/hypothesis): the five slot Hypotheses of a Founding Hypothesis, each with a [Metric](/business/nouns/metric) and a threshold. `slots`, inverse `slotOf`. - A Hypothesis **is stated by** one [Startup](/business/nouns/startup): a [Startup](/business/nouns/startup) states Hypotheses about itself, the Founding Hypothesis first, each settled by a [Metric](/business/nouns/metric) and a threshold. `statedBy`, inverse [`states`](/business/nouns/startup#rel-states). - A Hypothesis **has** many [Stories](/business/nouns/story): the Founding Hypothesis whose slots the [Story](/business/nouns/story) compiles from; a pivot recompiles it. `stories`, inverse [`compiledFrom`](/business/nouns/story#rel-compiled-from). - A Hypothesis **is tested by** many [Experiments](/business/nouns/experiment): each [Experiment](/business/nouns/experiment) settles one Hypothesis; many Experiments test one Hypothesis in turn. `testedBy`, inverse [`tests`](/business/nouns/experiment#rel-tests). - A Hypothesis **is tested by opening** one [Opening](/business/nouns/opening): a hire into an [Opening](/business/nouns/opening) must prove its Hypothesis. `testedByOpening`, inverse [`tests`](/business/nouns/opening#rel-tests). ## Lifecycle | State | Meaning | Moves to | | --- | --- | --- | | `open` (first) | Stated with its Metric and threshold, and bound to no Experiment. | `testing` by [Hypothesis.test](/business/nouns/hypothesis/test); `dropped` by [Hypothesis.drop](/business/nouns/hypothesis/drop) | | `testing` | An Experiment that decides it is running. | `supported` on [`Experiment.concluded`](/business/events/Experiment.concluded) when the Experiment’s Metric met this Hypothesis’s threshold; `refuted` on [`Experiment.concluded`](/business/events/Experiment.concluded) when the Experiment’s Metric missed this Hypothesis’s threshold; `dropped` by [Hypothesis.drop](/business/nouns/hypothesis/drop) | | `supported` | Its Experiment met the threshold; its outside Evidence grades how far that holds. | `testing` by [Hypothesis.test](/business/nouns/hypothesis/test); `dropped` by [Hypothesis.drop](/business/nouns/hypothesis/drop) | | `refuted` | Its Experiment missed the threshold; a merged Change can restate it and test it again. | `testing` by [Hypothesis.test](/business/nouns/hypothesis/test); `dropped` by [Hypothesis.drop](/business/nouns/hypothesis/drop) | | `dropped` | Retired from active work and kept on record with its Evidence. | None: it ends here. | ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Hypothesis.drop](/business/nouns/hypothesis/drop) | Drop retires a Hypothesis from active work and keeps it, with its Evidence, on record. | [Strategist](/agents/founding/strategist) | [`Hypothesis.dropped`](/business/events/Hypothesis.dropped) | None. | | [Hypothesis.test](/business/nouns/hypothesis/test) | Test binds a Hypothesis to the Experiment that decides it and moves the Hypothesis to testing. | [Strategist](/agents/founding/strategist) | [`Hypothesis.tested`](/business/events/Hypothesis.tested) | None. | | [Hypothesis.create](/business/nouns/hypothesis/create) | Creates a Hypothesis. Inherited from [Noun](/business/nouns/noun). | None. | `Hypothesis.created` | Two-way: `try`, `send`, `do` | | [Hypothesis.get](/business/nouns/hypothesis/get) | Returns one Hypothesis by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Hypothesis.list](/business/nouns/hypothesis/list) | Returns Hypotheses, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | A Hypothesis is kept forever and never edited: it has no `update` or `delete`. ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Hypothesis.create` | Yes | Yes | Yes | No | | `Hypothesis.get` | Yes | Yes | Yes | Yes | | `Hypothesis.list` | Yes | Yes | Yes | Yes | | `Hypothesis.drop` | Yes | Yes | Yes | No | | `Hypothesis.test` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Test the latest hypothesis with an experiment. ``` **API** ```bash curl -X POST https://api.sb/tutorloop.com/hypotheses/hypothesis_1/test \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"experiment":"experiment_1"}' ``` ```json { "api": "https://api.sb/tutorloop.com", "hypothesis": { "$id": "https://api.sb/tutorloop.com/hypotheses/hypothesis_1", "$type": "Hypothesis", "statement": "Matches high school students with math tutors.", "kind": "founding", "verdict": "Open", "version": 1 }, "action": { "$id": "https://api.sb/tutorloop.com/actions/action_1", "operation": "Hypothesis.test", "status": "done" }, "links": { "self": "https://api.sb/tutorloop.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const hypothesis = await $.Hypothesis.test({ hypothesis: 'hypothesis_1', experiment: 'experiment_1' }) ``` **CLI** ```bash npx startup-builder do Hypothesis.test --json '{"hypothesis":"hypothesis_1","experiment":"experiment_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Hypothesis.test({ hypothesis: 'hypothesis_1', experiment: 'experiment_1' })" } } ``` ## Example "Dental offices pay $99 a month to halve no-shows" is a Hypothesis with `metric` paid offices. Twelve paid offices within 30 days of the reservation link going out set `verdict: Supported`; fewer than four set `Refuted`. # test URL: /business/nouns/hypothesis/test · Id: `verb:Hypothesis.test` · Call: `await $.Hypothesis.test({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Test binds a Hypothesis to the Experiment that decides it and moves the Hypothesis to testing. Test binds a [Hypothesis](/business/nouns/hypothesis) to the [Experiment](/business/nouns/experiment) that decides it and moves the Hypothesis to testing. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `hypothesis` | [Hypothesis](/business/nouns/hypothesis) | Yes | The Hypothesis to test. | | `experiment` | [Experiment](/business/nouns/experiment) | Yes | The Experiment that decides it. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `hypothesis` | [Hypothesis](/business/nouns/hypothesis) | Yes | The Hypothesis, now testing. | ## Effects - Emits [`Hypothesis.tested`](/business/events/Hypothesis.tested). - Performed by the [Strategist](/agents/founding/strategist). ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Hypothesis.test](/business/nouns/hypothesis/test) | | The record is not in a state that allows this Verb, so the call is refused. | [`refused`](/code/api/errors/refused) | Read the record, run the Verb that moves it to an allowed state, then retry. | [Hypothesis.test](/business/nouns/hypothesis/test) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Test the latest hypothesis with an experiment. ``` **API** ```bash curl -X POST https://api.sb/tutorloop.com/hypotheses/hypothesis_1/test \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"experiment":"experiment_1"}' ``` ```json { "api": "https://api.sb/tutorloop.com", "hypothesis": { "$id": "https://api.sb/tutorloop.com/hypotheses/hypothesis_1", "$type": "Hypothesis", "statement": "Matches high school students with math tutors.", "kind": "founding", "verdict": "Open", "version": 1 }, "action": { "$id": "https://api.sb/tutorloop.com/actions/action_1", "operation": "Hypothesis.test", "status": "done" }, "links": { "self": "https://api.sb/tutorloop.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const hypothesis = await $.Hypothesis.test({ hypothesis: 'hypothesis_1', experiment: 'experiment_1' }) ``` **CLI** ```bash npx startup-builder do Hypothesis.test --json '{"hypothesis":"hypothesis_1","experiment":"experiment_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Hypothesis.test({ hypothesis: 'hypothesis_1', experiment: 'experiment_1' })" } } ``` Next: [`Experiment.start`](/business/nouns/experiment/start) (in `guide:spend-200-to-test-faster`). Guides that call it: [Spend $200 to test faster](/start/guides/spend-200-to-test-faster). # ICP URL: /business/nouns/icp · Id: `noun:icp` > An ICP is the ideal customer profile a Startup is built to win: who they are and what they do. An ICP is the ideal customer profile a [Startup](/business/nouns/startup) is built to win: who they are and what they do. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `description` | `text` | Yes | Who they are and what they do. | ## Object ```json { "$id": "https://api.sb/quietcopy.com/icps/icp_1", "$type": "ICP", "description": "One résumé reviewed against one job posting." } ``` ## Relationships - An ICP **faces** many [Problems](/business/nouns/problem): an ICP struggles with [Problems](/business/nouns/problem): how they solve them today and what that costs. `faces`, inverse [`facedBy`](/business/nouns/problem#rel-faced-by). - An ICP **has** many [Personas](/business/nouns/persona): a [Persona](/business/nouns/persona) is one named role inside an ICP, such as its buyer or its admin. `personas`, inverse [`belongsTo`](/business/nouns/persona#rel-belongs-to). - An ICP **is targeted by** many [Startups](/business/nouns/startup): a [Startup](/business/nouns/startup) is built to win its ICPs; its [Offers](/business/nouns/offer), [Story](/business/nouns/story) and [Plays](/business/nouns/play) compile toward them. `targetedBy`, inverse [`targets`](/business/nouns/startup#rel-targets). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [ICP.create](/business/nouns/icp/create) | Creates an ICP. Inherited from [Noun](/business/nouns/noun). | None. | `ICP.created` | Two-way: `try`, `send`, `do` | | [ICP.get](/business/nouns/icp/get) | Returns one ICP by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [ICP.list](/business/nouns/icp/list) | Returns ICPs, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [ICP.update](/business/nouns/icp/update) | Changes the given properties of an ICP. Inherited from [Noun](/business/nouns/noun). | None. | `ICP.updated` | Two-way: `try`, `send`, `do` | | [ICP.delete](/business/nouns/icp/delete) | Deletes an ICP; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `ICP.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `ICP.create` | Yes | Yes | Yes | No | | `ICP.get` | Yes | Yes | Yes | Yes | | `ICP.list` | Yes | Yes | Yes | Yes | | `ICP.update` | Yes | Yes | Yes | No | | `ICP.delete` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Add an ICP to TutorLoop. ``` **API** ```bash curl -X POST https://api.sb/tutorloop.com/icps \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"description":"One 50-minute online tutoring session."}' ``` ```json { "api": "https://api.sb/tutorloop.com", "icp": { "$id": "https://api.sb/tutorloop.com/icps/icp_1", "$type": "ICP", "description": "One 50-minute online tutoring session." }, "action": { "$id": "https://api.sb/tutorloop.com/actions/action_1", "operation": "ICP.create", "status": "done" }, "links": { "self": "https://api.sb/tutorloop.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const icp = await $.ICP.create({ description: 'One 50-minute online tutoring session.' }) ``` **CLI** ```bash npx startup-builder do ICP.create --json '{"description":"One 50-minute online tutoring session."}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.ICP.create({ description: 'One 50-minute online tutoring session.' })" } } ``` ## Example The ICP of a court-filings API is a litigation-support firm of 5 to 50 staff that pulls dockets by hand from four or more courts. # Idea URL: /business/nouns/idea · Id: `noun:idea` > An Idea is a business concept that exists apart from any Startup that pursues it and outlives each one. An Idea is a business concept that exists apart from any [Startup](/business/nouns/startup) that pursues it and outlives each one. Many Startups test one Idea as [Variants](/business/nouns/variant). ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `statement` | `text` | Yes | The concept in one line. | | `status` | `string` | Yes | One of `open` or `pursued`. | ## Object ```json { "$id": "https://api.sb/ledgerlark.com/ideas/idea_1", "$type": "Idea", "statement": "Keeps the books for independent contractors.", "status": "open" } ``` ## Relationships - An Idea **is pursued by** many [Startups](/business/nouns/startup): many [Startups](/business/nouns/startup) can test one Idea side by side; the Idea outlives each Startup that pursues it. `pursuedBy`, inverse [`pursues`](/business/nouns/startup#rel-pursues). ## Lifecycle | State | Meaning | Moves to | | --- | --- | --- | | `open` (first) | No Startup pursues it yet. | `pursued` by [Idea.pursue](/business/nouns/idea/pursue) | | `pursued` | At least one Startup tests it; each further pursue adds a variant to the same Experiment. | None: it ends here. | ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Idea.pursue](/business/nouns/idea/pursue) | Pursue starts a Startup on an Idea as one variant of the Experiment that tests the Idea. | [Founder](/agents/founding/founder) | [`Idea.pursued`](/business/events/Idea.pursued) | None. | | [Idea.create](/business/nouns/idea/create) | Creates an Idea. Inherited from [Noun](/business/nouns/noun). | None. | `Idea.created` | Two-way: `try`, `send`, `do` | | [Idea.get](/business/nouns/idea/get) | Returns one Idea by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Idea.list](/business/nouns/idea/list) | Returns Ideas, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | An Idea is kept forever and never edited: it has no `update` or `delete`. ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Idea.create` | Yes | Yes | Yes | No | | `Idea.get` | Yes | Yes | Yes | Yes | | `Idea.list` | Yes | Yes | Yes | Yes | | `Idea.pursue` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Pursue the latest idea. ``` **API** ```bash curl -X POST https://api.sb/shiftnote.app/ideas/idea_1/pursue \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/shiftnote.app", "startup": { "$id": "https://api.sb/shiftnote.app/startups/startup_1", "$type": "Startup", "name": "ShiftNote" }, "idea": { "$id": "https://api.sb/shiftnote.app/ideas/idea_1", "$type": "Idea", "statement": "Schedules shifts for small medical clinics.", "status": "open" }, "action": { "$id": "https://api.sb/shiftnote.app/actions/action_1", "operation": "Idea.pursue", "status": "done" }, "links": { "self": "https://api.sb/shiftnote.app/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { startup, idea } = await $.Idea.pursue({ idea: 'idea_1' }) ``` **CLI** ```bash npx startup-builder do Idea.pursue --json '{"idea":"idea_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Idea.pursue({ idea: 'idea_1' })" } } ``` ## Example The Idea "invoicing for dentists" drives four Startups at once, each with its own [Brand](/business/nouns/brand) and [Price](/business/nouns/price). Three stall; the Idea outlives them and seeds a fifth. # pursue URL: /business/nouns/idea/pursue · Id: `verb:Idea.pursue` · Call: `await $.Idea.pursue({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Pursue starts a Startup on an Idea as one variant of the Experiment that tests the Idea. Pursue starts a [Startup](/business/nouns/startup) on an [Idea](/business/nouns/idea) as one variant of the [Experiment](/business/nouns/experiment) that tests the Idea. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `idea` | [Idea](/business/nouns/idea) | Yes | The Idea to pursue. | | `template` | [Template](/business/nouns/template) | No | The Template the variant extends. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `startup` | [Startup](/business/nouns/startup) | Yes | The new variant Startup. | | `idea` | [Idea](/business/nouns/idea) | Yes | The Idea now pursued. | ## Effects - Emits [`Idea.pursued`](/business/events/Idea.pursued). - Performed by the [Founder](/agents/founding/founder). - Adds the Startup as a variant of the Idea’s Experiment. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The input does not match the schema of the operation. | [`invalid-input`](/code/api/errors/invalid-input) | Read the schema of the operation, then send every required field with the right type. | [Idea.pursue](/business/nouns/idea/pursue) | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Idea.pursue](/business/nouns/idea/pursue) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Pursue the latest idea. ``` **API** ```bash curl -X POST https://api.sb/shiftnote.app/ideas/idea_1/pursue \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/shiftnote.app", "startup": { "$id": "https://api.sb/shiftnote.app/startups/startup_1", "$type": "Startup", "name": "ShiftNote" }, "idea": { "$id": "https://api.sb/shiftnote.app/ideas/idea_1", "$type": "Idea", "statement": "Schedules shifts for small medical clinics.", "status": "open" }, "action": { "$id": "https://api.sb/shiftnote.app/actions/action_1", "operation": "Idea.pursue", "status": "done" }, "links": { "self": "https://api.sb/shiftnote.app/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { startup, idea } = await $.Idea.pursue({ idea: 'idea_1' }) ``` **CLI** ```bash npx startup-builder do Idea.pursue --json '{"idea":"idea_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Idea.pursue({ idea: 'idea_1' })" } } ``` # Implementation URL: /business/nouns/implementation · Id: `noun:implementation` > An Implementation is how an Interface, System, or Verb of a Product runs: managed by the platform, custom code on it, or external. An Implementation is how an [Interface](/business/nouns/interface), [System](/business/nouns/system), or [Verb](/business/nouns/verb) of a [Product](/business/nouns/product) runs: managed by the platform, custom code on it, or external. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `kind` | `string` | Yes | One of `managed`, `custom`, or `external`. | | `endpoint` | `url` | No | For an external Implementation, where api.sb routes each call. | | `deliverBy` | `date` | No | For a `declared` Implementation: when a Function runs the Verb; a missed date refunds every reserve. | ## Object ```json { "$id": "https://api.sb/quietcopy.com/implementations/implementation_1", "$type": "Implementation", "kind": "managed", "endpoint": "https://quietcopy.com", "deliverBy": "2026-10-22" } ``` ## Relationships - An Implementation **runs** one [Product](/business/nouns/product): an Implementation runs an [Interface](/business/nouns/interface), [System](/business/nouns/system) or [Verb](/business/nouns/verb) of one [Product](/business/nouns/product). `runs`, inverse [`implementations`](/business/nouns/product#rel-implementations). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Implementation.create](/business/nouns/implementation/create) | Creates an Implementation. Inherited from [Noun](/business/nouns/noun). | None. | `Implementation.created` | Two-way: `try`, `send`, `do` | | [Implementation.get](/business/nouns/implementation/get) | Returns one Implementation by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Implementation.list](/business/nouns/implementation/list) | Returns Implementations, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Implementation.update](/business/nouns/implementation/update) | Changes the given properties of an Implementation. Inherited from [Noun](/business/nouns/noun). | None. | `Implementation.updated` | Two-way: `try`, `send`, `do` | | [Implementation.delete](/business/nouns/implementation/delete) | Deletes an Implementation; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Implementation.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Implementation.create` | Yes | Yes | Yes | No | | `Implementation.get` | Yes | Yes | Yes | Yes | | `Implementation.list` | Yes | Yes | Yes | Yes | | `Implementation.update` | Yes | Yes | Yes | No | | `Implementation.delete` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Add an implementation to TutorLoop. ``` **API** ```bash curl -X POST https://api.sb/tutorloop.com/implementations \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"kind":"managed"}' ``` ```json { "api": "https://api.sb/tutorloop.com", "implementation": { "$id": "https://api.sb/tutorloop.com/implementations/implementation_1", "$type": "Implementation", "kind": "managed" }, "action": { "$id": "https://api.sb/tutorloop.com/actions/action_1", "operation": "Implementation.create", "status": "done" }, "links": { "self": "https://api.sb/tutorloop.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const implementation = await $.Implementation.create({ kind: 'managed' }) ``` **CLI** ```bash npx startup-builder do Implementation.create --json '{"kind":"managed"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Implementation.create({ kind: 'managed' })" } } ``` ## Example A permit tracker runs managed, except `Inspection.book`: its Implementation has kind `external` and an endpoint on the county's scheduling server. The [Implementation chapter](/code/builders/software/implementation) explains each mode. # acknowledge URL: /business/nouns/incident/acknowledge · Id: `verb:Incident.acknowledge` · Call: `await $.Incident.acknowledge({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Acknowledge records that an on-call Worker owns an open Incident and stops its escalation. Acknowledge records that an on-call [Worker](/business/nouns/worker) owns an open [Incident](/business/nouns/incident) and stops its escalation. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `incident` | [Incident](/business/nouns/incident) | Yes | The open Incident. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `incident` | [Incident](/business/nouns/incident) | Yes | The acknowledged Incident. | ## Effects - Emits [`Incident.acknowledged`](/business/events/Incident.acknowledged). - Performed by the [Reliability Engineer](/agents/engineering/reliability-engineer). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Stops paging the next Worker in the rota. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Incident.acknowledge](/business/nouns/incident/acknowledge) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Acknowledge the latest incident. ``` **API** ```bash curl -X POST https://api.sb/petpantry.shop/incidents/incident_1/acknowledge \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/petpantry.shop", "incident": { "$id": "https://api.sb/petpantry.shop/incidents/incident_1", "$type": "Incident", "status": "pending", "mode": "try", "severity": "minor", "detectedAt": "2026-10-22T12:00:00Z" }, "action": { "$id": "https://api.sb/petpantry.shop/actions/action_1", "operation": "Incident.acknowledge", "status": "done" }, "links": { "self": "https://api.sb/petpantry.shop/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const incident = await $.Incident.acknowledge({ incident: 'incident_1' }) ``` **CLI** ```bash npx startup-builder do Incident.acknowledge --json '{"incident":"incident_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Incident.acknowledge({ incident: 'incident_1' })" } } ``` # Incident URL: /business/nouns/incident · Id: `noun:incident` > An Incident is an Issue where an Interface or Site fails Customers in production, tracked from detection to postmortem. An Incident is an [Issue](/business/nouns/issue) where an [Interface](/business/nouns/interface) or [Site](/business/nouns/site) fails [Customers](/business/nouns/customer) in production, tracked from detection to postmortem. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `severity` | `string` | Yes | One of `minor`, `major`, or `critical`. | | `detectedAt` | `datetime` | Yes | When monitoring or a Customer first reported it. | | `resolvedAt` | `datetime` | No | When service was restored. | | `personalData` | `boolean` | No | True when the Incident exposed personal data, which starts the breach-notice clock. |
Inherited from [Issue](/business/nouns/issue): 2 properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `kind` | `string` | No | One of `bug`, `request`, or `question`. | | `advisory` | `string` | No | For a vulnerability: the public advisory it matches, with the affected package and range. |
Inherited from [Task](/business/nouns/task): 3 properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `due` | `datetime` | No | When the Task is due. | | `priority` | `integer` | No | Its rank in the inbox, highest first. | | `recurrence` | `string` | No | The schedule a recurring duty repeats on. |
Inherited from [Action](/business/nouns/action): 11 properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `status` | `string` | Yes | One of `pending`, `done`, `failed`, `canceled`, or `refused`. | | `reason` | `string` | No | Why a pending Action waits: `queued`, `running`, `retrying`, `awaitingWorker`, `awaitingInput`, `awaitingSource`, `awaitingAction`, or `awaitingTime`. | | `mode` | `string` | Yes | How the caller invoked it: `try`, `send`, or `do`. | | `by` | [Worker](/business/nouns/worker) | No | The Worker that performed it. | | `for` | [Party](/business/nouns/party) | No | The Party it was done on behalf of. | | `via` | `string` | No | The Interface or request it arrived through. | | `on` | `string` | No | The Action or Event that caused it, such as the failed attempt a retry follows. | | `thing` | `string` | No | The record, at the Version the Action was decided against. | | `input` | `json` | No | The input it was called with. | | `createdAt` | `datetime` | No | When it was called. | | `reserved` | `money` | No | The most this Action may cost, held against its Limits from the check until it settles, billed misses included. |
## Object ```json { "$id": "https://api.sb/quietcopy.com/incidents/incident_1", "$type": "Incident", "status": "pending", "reason": "queued", "mode": "try", "by": "worker_1", "for": "party_1", "via": "API", "on": "Invoice.overdue", "thing": "invoice_1@v3", "input": {}, "createdAt": "2026-10-22T12:00:00Z", "reserved": { "amount": 39, "currency": "USD" }, "due": "2026-10-22T12:00:00Z", "priority": 1, "recurrence": "Weekly on Friday", "kind": "bug", "advisory": "GHSA-xxxx-xxxx-xxxx", "severity": "minor", "detectedAt": "2026-10-22T12:00:00Z", "resolvedAt": "2026-10-22T12:00:00Z", "personalData": true } ``` ## Relationships - An Incident **has** one [Monitor](/business/nouns/monitor): a failing internal [Monitor](/business/nouns/monitor) opens an Incident, which names the Monitor that saw it first. `monitor`, inverse [`opens`](/business/nouns/monitor#rel-opens). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Incident.acknowledge](/business/nouns/incident/acknowledge) | Acknowledge records that an on-call Worker owns an open Incident and stops its escalation. | [Reliability Engineer](/agents/engineering/reliability-engineer) | [`Incident.acknowledged`](/business/events/Incident.acknowledged) | Two-way: `try`, `send`, `do` | | [Incident.open](/business/nouns/incident/open) | Open starts an Incident from a failing Monitor, an error spike or a Metric past its threshold, and pages the on-call Worker. | [Reliability Engineer](/agents/engineering/reliability-engineer) | [`Incident.opened`](/business/events/Incident.opened) | Two-way: `try`, `send`, `do` | | [Incident.resolve](/business/nouns/incident/resolve) | Resolve closes an Incident once its Monitors pass, posts the resolution to the status page and opens the review Task. | [Reliability Engineer](/agents/engineering/reliability-engineer) | [`Incident.resolved`](/business/events/Incident.resolved) | Two-way: `try`, `send`, `do` | | [Incident.create](/business/nouns/incident/create) | Creates an Incident. Inherited from [Noun](/business/nouns/noun). | None. | `Incident.created` | Two-way: `try`, `send`, `do` | | [Incident.get](/business/nouns/incident/get) | Returns one Incident by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Incident.list](/business/nouns/incident/list) | Returns Incidents, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Incident.update](/business/nouns/incident/update) | Changes the given properties of an Incident. Inherited from [Noun](/business/nouns/noun). | None. | `Incident.updated` | Two-way: `try`, `send`, `do` | | [Incident.delete](/business/nouns/incident/delete) | Deletes an Incident; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Incident.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Incident.create` | Yes | Yes | Yes | No | | `Incident.get` | Yes | Yes | Yes | Yes | | `Incident.list` | Yes | Yes | Yes | Yes | | `Incident.update` | Yes | Yes | Yes | No | | `Incident.delete` | Yes | Yes | Yes | No | | `Incident.acknowledge` | Yes | Yes | Yes | No | | `Incident.open` | Yes | Yes | Yes | No | | `Incident.resolve` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Open the latest incident. ``` **API** ```bash curl -X POST https://api.sb/quietcopy.com/incidents/open \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"severity":"sev1","cause":"Example cause"}' ``` ```json { "api": "https://api.sb/quietcopy.com", "incident": { "$id": "https://api.sb/quietcopy.com/incidents/incident_1", "$type": "Incident", "status": "pending", "mode": "try", "severity": "minor", "detectedAt": "2026-10-22T12:00:00Z" }, "action": { "$id": "https://api.sb/quietcopy.com/actions/action_1", "operation": "Incident.open", "status": "done" }, "links": { "self": "https://api.sb/quietcopy.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const incident = await $.Incident.open({ severity: 'sev1', cause: 'Example cause' }) ``` **CLI** ```bash npx startup-builder do Incident.open --json '{"severity":"sev1","cause":"Example cause"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Incident.open({ severity: 'sev1', cause: 'Example cause' })" } } ``` ## Example Sign-in to a meal-planning [App](/business/nouns/app) fails for 9 minutes after a deploy. A major Incident opens at detection, the [Change](/business/nouns/change) reverts, and the postmortem links the fix that prevents a repeat. # open URL: /business/nouns/incident/open · Id: `verb:Incident.open` · Call: `await $.Incident.open({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Open starts an Incident from a failing Monitor, an error spike or a Metric past its threshold, and pages the on-call Worker. Open starts an [Incident](/business/nouns/incident) from a failing [Monitor](/business/nouns/monitor), an error spike or a [Metric](/business/nouns/metric) past its threshold, and pages the on-call [Worker](/business/nouns/worker). ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `severity` | `string` | Yes | `sev1` stops Customers, `sev2` degrades a core path, `sev3` degrades one feature. | | `cause` | `string` | Yes | The Monitor, error group or Metric that tripped it. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `incident` | [Incident](/business/nouns/incident) | Yes | The open Incident. | ## Effects - Emits [`Incident.opened`](/business/events/Incident.opened). - Performed by the [Reliability Engineer](/agents/engineering/reliability-engineer). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Pages the on-call Worker, agent first, and a Human after five minutes unacknowledged. - Never holds a rollback or a guardrail stop. - Posts `sev1` and `sev2` Incidents to the status page. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Incident.open](/business/nouns/incident/open) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Open the latest incident. ``` **API** ```bash curl -X POST https://api.sb/quietcopy.com/incidents/open \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"severity":"sev1","cause":"Example cause"}' ``` ```json { "api": "https://api.sb/quietcopy.com", "incident": { "$id": "https://api.sb/quietcopy.com/incidents/incident_1", "$type": "Incident", "status": "pending", "mode": "try", "severity": "minor", "detectedAt": "2026-10-22T12:00:00Z" }, "action": { "$id": "https://api.sb/quietcopy.com/actions/action_1", "operation": "Incident.open", "status": "done" }, "links": { "self": "https://api.sb/quietcopy.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const incident = await $.Incident.open({ severity: 'sev1', cause: 'Example cause' }) ``` **CLI** ```bash npx startup-builder do Incident.open --json '{"severity":"sev1","cause":"Example cause"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Incident.open({ severity: 'sev1', cause: 'Example cause' })" } } ``` # resolve URL: /business/nouns/incident/resolve · Id: `verb:Incident.resolve` · Call: `await $.Incident.resolve({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Resolve closes an Incident once its Monitors pass, posts the resolution to the status page and opens the review Task. Resolve closes an [Incident](/business/nouns/incident) once its [Monitors](/business/nouns/monitor) pass, posts the resolution to the status page and opens the review [Task](/business/nouns/task). ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `incident` | [Incident](/business/nouns/incident) | Yes | The Incident to close. | | `summary` | `text` | Yes | What failed and what fixed it. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `incident` | [Incident](/business/nouns/incident) | Yes | The resolved Incident. | ## Effects - Emits [`Incident.resolved`](/business/events/Incident.resolved). - Performed by the [Reliability Engineer](/agents/engineering/reliability-engineer). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Opens a postmortem Task due within five business days. - Notifies status page subscribers. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Incident.resolve](/business/nouns/incident/resolve) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Resolve the latest incident. ``` **API** ```bash curl -X POST https://api.sb/petpantry.shop/incidents/incident_1/resolve \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"summary":"Example summary"}' ``` ```json { "api": "https://api.sb/petpantry.shop", "incident": { "$id": "https://api.sb/petpantry.shop/incidents/incident_1", "$type": "Incident", "status": "pending", "mode": "try", "severity": "minor", "detectedAt": "2026-10-22T12:00:00Z" }, "action": { "$id": "https://api.sb/petpantry.shop/actions/action_1", "operation": "Incident.resolve", "status": "done" }, "links": { "self": "https://api.sb/petpantry.shop/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const incident = await $.Incident.resolve({ incident: 'incident_1', summary: 'Example summary' }) ``` **CLI** ```bash npx startup-builder do Incident.resolve --json '{"incident":"incident_1","summary":"Example summary"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Incident.resolve({ incident: 'incident_1', summary: 'Example summary' })" } } ``` # cancel URL: /business/nouns/instrument/cancel · Id: `verb:Instrument.cancel` · Call: `await $.Instrument.cancel({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Cancel ends an unvested, expired or forfeited Instrument and returns any option Shares to the pool. Cancel ends an unvested, expired or forfeited [Instrument](/business/nouns/instrument) and returns any option [Shares](/business/nouns/share) to the pool. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `instrument` | [Instrument](/business/nouns/instrument) | Yes | The Instrument to end. | | `reason` | `string` | Yes | Why it ends: `unvested`, `expired` or `forfeited`. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `instrument` | [Instrument](/business/nouns/instrument) | Yes | The canceled Instrument, kept with its history. | ## Effects - Emits [`Instrument.canceled`](/business/events/Instrument.canceled). - Performed by the [Legal Lead](/agents/legal/legal-lead). - One-way: it waits out its delay window, and runs in the `send` and `do` modes. - Returns option Shares to the unallocated pool. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Instrument.cancel](/business/nouns/instrument/cancel) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Medium: one-way, bounded | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | 1 business hour, in which a watcher can pause, redirect or cancel it; then it runs. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Cancel the latest instrument. ``` **API** ```bash curl -X POST https://api.sb/patentpad.com/instruments/instrument_1/cancel \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"reason":"unvested"}' ``` ```json { "api": "https://api.sb/patentpad.com", "instrument": { "$id": "https://api.sb/patentpad.com/instruments/instrument_1", "$type": "Instrument", "kind": "safe", "status": "outstanding" }, "action": { "$id": "https://api.sb/patentpad.com/actions/action_1", "operation": "Instrument.cancel", "status": "done" }, "links": { "self": "https://api.sb/patentpad.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const instrument = await $.Instrument.cancel({ instrument: 'instrument_1', reason: 'unvested' }) ``` **CLI** ```bash npx startup-builder do Instrument.cancel --json '{"instrument":"instrument_1","reason":"unvested"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Instrument.cancel({ instrument: 'instrument_1', reason: 'unvested' })" } } ``` # convert URL: /business/nouns/instrument/convert · Id: `verb:Instrument.convert` · Call: `await $.Instrument.convert({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Convert turns a SAFE or note into Shares at a priced round, at its cap or discount, whichever gives more Shares. Convert turns a SAFE or note into [Shares](/business/nouns/share) at a priced round, at its cap or discount, whichever gives more Shares. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `instrument` | [Instrument](/business/nouns/instrument) | Yes | The SAFE or note. | | `roundPrice` | `money` | Yes | The price per Share of the priced round. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `shares` | list of [Share](/business/nouns/share) | Yes | The Shares issued on conversion. | | `instrument` | [Instrument](/business/nouns/instrument) | Yes | The Instrument, now converted. | ## Effects - Emits [`Instrument.converted`](/business/events/Instrument.converted). - Performed by the [Legal Lead](/agents/legal/legal-lead). - One-way (money): it waits out its delay window, and runs in the `send` and `do` modes. - Applies most-favored-nation terms when a later Instrument got better ones. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Instrument.convert](/business/nouns/instrument/convert) | ## When it waits | Gate | Default | | --- | --- | | Decision class | High: one-way, broad (money) | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | 1 business day, in which a watcher can pause, redirect or cancel it; then it runs. | | Limit | The spend [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) or [Mandate](/business/nouns/mandate) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Convert the latest instrument. ``` **API** ```bash curl -X POST https://api.sb/kilnbakery.com/instruments/instrument_1/convert \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"roundPrice":{"amount":9,"currency":"USD"}}' ``` ```json { "api": "https://api.sb/kilnbakery.com", "shares": [ { "$id": "https://api.sb/kilnbakery.com/shares/share_1", "$type": "Share", "class": "common", "quantity": 1 } ], "instrument": { "$id": "https://api.sb/kilnbakery.com/instruments/instrument_1", "$type": "Instrument", "kind": "safe", "status": "outstanding" }, "action": { "$id": "https://api.sb/kilnbakery.com/actions/action_1", "operation": "Instrument.convert", "status": "done" }, "links": { "self": "https://api.sb/kilnbakery.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { shares, instrument } = await $.Instrument.convert({ instrument: 'instrument_1', roundPrice: { amount: 9, currency: 'USD' } }) ``` **CLI** ```bash npx startup-builder do Instrument.convert --json '{"instrument":"instrument_1","roundPrice":{"amount":9,"currency":"USD"}}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Instrument.convert({ instrument: 'instrument_1', roundPrice: { amount: 9, currency: 'USD' } })" } } ``` # exercise URL: /business/nouns/instrument/exercise · Id: `verb:Instrument.exercise` · Call: `await $.Instrument.exercise({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Exercise buys the Shares an option or warrant covers at its strike price, up to what has vested. Exercise buys the [Shares](/business/nouns/share) an option or warrant covers at its strike price, up to what has vested. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `instrument` | [Instrument](/business/nouns/instrument) | Yes | The option or warrant. | | `quantity` | `integer` | Yes | How many Shares to buy. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `share` | [Share](/business/nouns/share) | Yes | The Shares bought. | | `instrument` | [Instrument](/business/nouns/instrument) | Yes | The Instrument, now exercised. | ## Effects - Emits [`Instrument.exercised`](/business/events/Instrument.exercised). - Performed by the [Legal Lead](/agents/legal/legal-lead). - One-way (money): it waits out its delay window, and runs in the `send` and `do` modes. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Instrument.exercise](/business/nouns/instrument/exercise) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Medium: one-way, bounded (money) | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | 1 business hour, in which a watcher can pause, redirect or cancel it; then it runs. | | Limit | The spend [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) or [Mandate](/business/nouns/mandate) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Exercise the latest instrument. ``` **API** ```bash curl -X POST https://api.sb/patentpad.com/instruments/instrument_1/exercise \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"quantity":1}' ``` ```json { "api": "https://api.sb/patentpad.com", "share": { "$id": "https://api.sb/patentpad.com/shares/share_1", "$type": "Share", "class": "common", "quantity": 1 }, "instrument": { "$id": "https://api.sb/patentpad.com/instruments/instrument_1", "$type": "Instrument", "kind": "safe", "status": "outstanding" }, "action": { "$id": "https://api.sb/patentpad.com/actions/action_1", "operation": "Instrument.exercise", "status": "done" }, "links": { "self": "https://api.sb/patentpad.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { share, instrument } = await $.Instrument.exercise({ instrument: 'instrument_1', quantity: 1 }) ``` **CLI** ```bash npx startup-builder do Instrument.exercise --json '{"instrument":"instrument_1","quantity":1}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Instrument.exercise({ instrument: 'instrument_1', quantity: 1 })" } } ``` # grant URL: /business/nouns/instrument/grant · Id: `verb:Instrument.grant` · Call: `await $.Instrument.grant({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Grant gives a Holder an option from the pool, with its strike price, vesting schedule and cliff. Grant gives a [Holder](/business/nouns/holder) an option from the pool, with its strike price, vesting schedule and cliff. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `holder` | [Holder](/business/nouns/holder) | Yes | The Holder who receives the option, usually a Worker. | | `quantity` | `integer` | Yes | The Shares the option covers. | | `strike` | `money` | Yes | The exercise price, at or above the latest fair market value. | | `vesting` | `json` | Yes | The schedule and cliff. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `instrument` | [Instrument](/business/nouns/instrument) | Yes | The granted option. | ## Effects - Emits [`Instrument.granted`](/business/events/Instrument.granted). - Performed by the [Legal Lead](/agents/legal/legal-lead). - One-way: it waits out its delay window, and runs in the `send` and `do` modes. - Refuses a strike below the latest 409A fair market value. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Instrument.grant](/business/nouns/instrument/grant) | | A strike below the latest 409A fair market value | [`refused`](/code/api/errors/refused) | Clear what the check names, then call it again. | [Instrument.grant](/business/nouns/instrument/grant) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Medium: one-way, bounded | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | 1 business hour, in which a watcher can pause, redirect or cancel it; then it runs. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Grant the latest instrument with a holder. ``` **API** ```bash curl -X POST https://api.sb/patentpad.com/instruments/grant \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"holder":"holder_1","quantity":1,"strike":{"amount":499,"currency":"USD"},"vesting":{}}' ``` ```json { "api": "https://api.sb/patentpad.com", "instrument": { "$id": "https://api.sb/patentpad.com/instruments/instrument_1", "$type": "Instrument", "kind": "safe", "status": "outstanding" }, "action": { "$id": "https://api.sb/patentpad.com/actions/action_1", "operation": "Instrument.grant", "status": "done" }, "links": { "self": "https://api.sb/patentpad.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const instrument = await $.Instrument.grant({ holder: 'holder_1', quantity: 1, strike: { amount: 499, currency: 'USD' }, vesting: {} }) ``` **CLI** ```bash npx startup-builder do Instrument.grant --json '{"holder":"holder_1","quantity":1,"strike":{"amount":499,"currency":"USD"},"vesting":{}}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Instrument.grant({ holder: 'holder_1', quantity: 1, strike: { amount: 499, currency: 'USD' }, vesting: {} })" } } ``` # Instrument URL: /business/nouns/instrument · Id: `noun:instrument` > An Instrument is a right to future ownership in a Company: a SAFE, a note, an option or a warrant. An Instrument is a right to future ownership in a [Company](/business/nouns/company): a SAFE, a note, an option or a warrant. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `kind` | `string` | Yes | Which right: `safe`, `note`, `option` or `warrant`. | | `amount` | `money` | No | The amount invested, for a SAFE or a note. | | `cap` | `money` | No | The valuation cap a SAFE or note converts at. | | `discount` | `number` | No | The percent discount to the next priced round a SAFE or note converts at. | | `strike` | `money` | No | The price per Share an option or warrant exercises at. | | `quantity` | `integer` | No | The Shares an option or warrant covers. | | `vesting` | `json` | No | The vesting schedule and cliff of an option grant. | | `status` | `string` | Yes | Where it stands; a canceled or converted Instrument is kept, never deleted. | ## Object ```json { "$id": "https://api.sb/patentpad.com/instruments/instrument_1", "$type": "Instrument", "kind": "safe", "amount": { "amount": 499, "currency": "USD" }, "cap": { "amount": 499, "currency": "USD" }, "discount": 1, "strike": { "amount": 499, "currency": "USD" }, "quantity": 1, "vesting": {}, "status": "outstanding" } ``` ## Relationships - An Instrument **is held by** one [Holder](/business/nouns/holder): each Instrument belongs to one [Holder](/business/nouns/holder), who sees it, its vesting and its documents. `heldBy`, inverse [`instruments`](/business/nouns/holder#rel-instruments). - An Instrument **is issued by** one [Company](/business/nouns/company): an Instrument is a right in one [Company](/business/nouns/company) and counts in its fully diluted cap table. `issuedBy`, inverse [`instruments`](/business/nouns/company#rel-instruments). ## Lifecycle | State | Meaning | Moves to | | --- | --- | --- | | `outstanding` (first) | Granted or issued and not yet turned into Shares. | `converted` by [Instrument.convert](/business/nouns/instrument/convert); `exercised` by [Instrument.exercise](/business/nouns/instrument/exercise); `canceled` by [Instrument.cancel](/business/nouns/instrument/cancel) | | `converted` | A SAFE or note turned into Shares at a priced round. | None: it ends here. | | `exercised` | Every Share it covers was bought at the strike price; a partial exercise keeps it outstanding. | None: it ends here. | | `canceled` | Ended unvested, expired or forfeited, with any option Shares back in the pool. | None: it ends here. | ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Instrument.cancel](/business/nouns/instrument/cancel) | Cancel ends an unvested, expired or forfeited Instrument and returns any option Shares to the pool. | [Legal Lead](/agents/legal/legal-lead) | [`Instrument.canceled`](/business/events/Instrument.canceled) | One-way: `send`, `do` | | [Instrument.convert](/business/nouns/instrument/convert) | Convert turns a SAFE or note into Shares at a priced round, at its cap or discount, whichever gives more Shares. | [Legal Lead](/agents/legal/legal-lead) | [`Instrument.converted`](/business/events/Instrument.converted) | One-way (money): `send`, `do` | | [Instrument.exercise](/business/nouns/instrument/exercise) | Exercise buys the Shares an option or warrant covers at its strike price, up to what has vested. | [Legal Lead](/agents/legal/legal-lead) | [`Instrument.exercised`](/business/events/Instrument.exercised) | One-way (money): `send`, `do` | | [Instrument.grant](/business/nouns/instrument/grant) | Grant gives a Holder an option from the pool, with its strike price, vesting schedule and cliff. | [Legal Lead](/agents/legal/legal-lead) | [`Instrument.granted`](/business/events/Instrument.granted) | One-way: `send`, `do` | | [Instrument.get](/business/nouns/instrument/get) | Returns one Instrument by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Instrument.list](/business/nouns/instrument/list) | Returns Instruments, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | An Instrument is kept forever and never edited: it has no `update` or `delete`. ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Instrument.get` | Yes | Yes | Yes | Yes | | `Instrument.list` | Yes | Yes | Yes | Yes | | `Instrument.cancel` | Yes | No | No | No | | `Instrument.convert` | Yes | No | No | No | | `Instrument.exercise` | Yes | No | No | No | | `Instrument.grant` | Yes | No | No | No | ## Call it **Ask** ```text Grant the latest instrument with a holder. ``` **API** ```bash curl -X POST https://api.sb/patentpad.com/instruments/grant \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"holder":"holder_1","quantity":1,"strike":{"amount":499,"currency":"USD"},"vesting":{}}' ``` ```json { "api": "https://api.sb/patentpad.com", "instrument": { "$id": "https://api.sb/patentpad.com/instruments/instrument_1", "$type": "Instrument", "kind": "safe", "status": "outstanding" }, "action": { "$id": "https://api.sb/patentpad.com/actions/action_1", "operation": "Instrument.grant", "status": "done" }, "links": { "self": "https://api.sb/patentpad.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const instrument = await $.Instrument.grant({ holder: 'holder_1', quantity: 1, strike: { amount: 499, currency: 'USD' }, vesting: {} }) ``` **CLI** ```bash npx startup-builder do Instrument.grant --json '{"holder":"holder_1","quantity":1,"strike":{"amount":499,"currency":"USD"},"vesting":{}}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Instrument.grant({ holder: 'holder_1', quantity: 1, strike: { amount: 499, currency: 'USD' }, vesting: {} })" } } ``` ## Example A [Company](/business/nouns/company) raises $250,000 on a SAFE with an $8 million cap. At the next priced round the Instrument converts to [Shares](/business/nouns/share), and its record stays with status `converted`. # call URL: /business/nouns/integration/call · Id: `verb:Integration.call` · Call: `await $.Integration.call({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Call sends one request to an upstream through an Integration, with its token filled in server-side, for endpoints no Mapping covers. Call sends one request to an upstream through an [Integration](/business/nouns/integration), with its token filled in server-side, for endpoints no [Mapping](/business/nouns/mapping) covers. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `integration` | [Integration](/business/nouns/integration) | Yes | The Integration to call through. | | `method` | `string` | Yes | The HTTP method; `GET` runs at once. | | `path` | `string` | Yes | The upstream path, inside the Integration’s grants. | | `body` | `json` | No | The request body. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `status` | `integer` | Yes | The upstream’s status code. | | `body` | `json` | No | The upstream’s response body. | | `integration` | [Integration](/business/nouns/integration) | Yes | The Integration the request went through. | ## Effects - Emits [`Integration.called`](/business/events/Integration.called). - Performed by the [Integration Engineer](/agents/engineering/integration-engineer). - One-way (customer): it waits out its delay window, and runs in the `send` and `do` modes. - Fills the token server-side; no Worker reads it. - Runs a `GET` at once and waits the delay window for any other method until a Mapping classes the endpoint two-way. - Refuses a path outside the Integration’s grants before it leaves the platform. - `try` runs the upstream’s own validation and changes nothing. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Integration.call](/business/nouns/integration/call) | | A path outside the Integration’s grants before it leaves the platform | [`refused`](/code/api/errors/refused) | Clear what the check names, then call it again. | [Integration.call](/business/nouns/integration/call) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Medium: one-way, bounded (customer) | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | 1 business hour, in which a watcher can pause, redirect or cancel it; then it runs. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Call the latest integration. ``` **API** ```bash curl -X POST https://api.sb/petpantry.shop/integrations/integration_1/call \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"method":"GET","path":"/"}' ``` ```json { "api": "https://api.sb/petpantry.shop", "status": 1, "body": {}, "integration": { "$id": "https://api.sb/petpantry.shop/integrations/integration_1", "$type": "Integration", "acquired": "owned", "scope": "studio", "mode": "mirror", "state": "connecting" }, "action": { "$id": "https://api.sb/petpantry.shop/actions/action_1", "operation": "Integration.call", "status": "done" }, "links": { "self": "https://api.sb/petpantry.shop/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { status, body, integration } = await $.Integration.call({ integration: 'integration_1', method: 'GET', path: '/' }) ``` **CLI** ```bash npx startup-builder do Integration.call --json '{"integration":"integration_1","method":"GET","path":"/"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Integration.call({ integration: 'integration_1', method: 'GET', path: '/' })" } } ``` # connect URL: /business/nouns/integration/connect · Id: `verb:Integration.connect` · Call: `await $.Integration.connect({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Connect asks an account holder to approve an outside account for one System and records the grants they approve. Connect asks an account holder to approve an outside account for one [System](/business/nouns/system) and records the grants they approve. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `system` | [System](/business/nouns/system) | Yes | The System the Integration serves. | | `scope` | `string` | Yes | One of `studio`, `startup` or `customer`; a person’s own account is `startup`, narrowed to them. | | `grants` | `string[]` | Yes | The access requested, shown to the account holder before they approve. | | `venue` | `string` | No | The id of the ad, social or app-store venue the account is on. | | `for` | [Party](/business/nouns/party) | No | The account holder, when an Agent asks on their behalf. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `integration` | [Integration](/business/nouns/integration) | Yes | The Integration, `connecting` until approved. | | `connectUrl` | `url` | Yes | The approval page on the upstream’s own site; it expires in one hour. | ## Effects - Emits [`Integration.connected`](/business/events/Integration.connected). - Performed by the [Integration Engineer](/agents/engineering/integration-engineer). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Moves the Integration to `connected` when the account holder approves. - Stores the token in Secrets, where no Worker reads it. - Records the approver as `connectedBy`, the outside account and the grants. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Integration.connect](/business/nouns/integration/connect) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Medium: two-way, visible | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | 1 business hour, in which a watcher can pause, redirect or cancel it; then it runs. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Connect the latest integration with a system. ``` **API** ```bash curl -X POST https://api.sb/petpantry.shop/integrations/connect \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"system":"system_1","scope":"studio","grants":["Example grants"]}' ``` ```json { "api": "https://api.sb/petpantry.shop", "integration": { "$id": "https://api.sb/petpantry.shop/integrations/integration_1", "$type": "Integration", "acquired": "owned", "scope": "studio", "mode": "mirror", "state": "connecting" }, "connectUrl": "https://petpantry.shop", "action": { "$id": "https://api.sb/petpantry.shop/actions/action_1", "operation": "Integration.connect", "status": "done" }, "links": { "self": "https://api.sb/petpantry.shop/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { integration, connectUrl } = await $.Integration.connect({ system: 'system_1', scope: 'studio', grants: ['Example grants'] }) ``` **CLI** ```bash npx startup-builder do Integration.connect --json '{"system":"system_1","scope":"studio","grants":["Example grants"]}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Integration.connect({ system: 'system_1', scope: 'studio', grants: ['Example grants'] })" } } ``` Next: [`Integration.sync`](/business/nouns/integration/sync) (in `guide:sell-on-aws-marketplace`). Guides that call it: [Sell on AWS Marketplace](/products/offers/sell-on-aws-marketplace). # Integration URL: /business/nouns/integration · Id: `noun:integration` > An Integration is an outside Source connected to a System with credentials, at Studio, Startup, or Customer scope. An Integration is an outside [Source](/business/nouns/source) connected to a [System](/business/nouns/system) with credentials, at [Studio](/business/nouns/studio), [Startup](/business/nouns/startup), or [Customer](/business/nouns/customer) scope. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `scope` | `string` | Yes | One of `studio`, `startup`, or `customer`. | | `sync` | `string` | No | Which side leads a sync connector: `platform` or `provider`. | | `mode` | `string` | Yes | How records move: `mirror` writes db.sb out to the outside tool; `import` turns edits there into Changes. db.sb is the record in both. | | `state` | `string` | Yes | Where the connected account stands; read fresh before every call. | | `venue` | `string` | No | The id of the ad, social or app-store venue the account is on, when it is on one. | | `account` | `string` | No | The outside account’s own id, such as an ad account, a workspace or a repository. | | `grants` | `string[]` | No | The outside permissions the account holder approved: the narrowest set its Verbs need. | | `connectedBy` | [Party](/business/nouns/party) | No | Who approved the connection; a Human’s own account is used only under that Human’s Mandate. | | `environment` | `string` | No | A `test` Integration reaches only the upstream’s test account, as a Stripe test account does. | | `expiresAt` | `datetime` | No | When access lapses unless refreshed. | | `refreshedAt` | `datetime` | No | When the platform last renewed the outside token. | | `lastError` | `string` | No | The error slug of the last failed call or refresh, cleared by the next success. | | `cursor` | `string` | No | Where the last sync run stopped, so the next run reads only what changed. |
Inherited from [Source](/business/nouns/source): 2 properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `acquired` | `string` | Yes | One of `owned`, `wrapped`, or `recruited`. | | `terms` | `text` | No | The terms the Startup holds the right to use and resell it under. |
## Object ```json { "$id": "https://api.sb/petpantry.shop/integrations/integration_1", "$type": "Integration", "acquired": "owned", "terms": "Resale allowed under the provider’s published API terms; 10,000 calls a month included.", "scope": "studio", "sync": "Example sync", "mode": "mirror", "state": "connecting", "venue": "Example venue", "account": "Example account", "grants": [ "Example grants" ], "connectedBy": "party_1", "environment": "test", "expiresAt": "2026-10-22T12:00:00Z", "refreshedAt": "2026-10-22T12:00:00Z", "lastError": "Example last error", "cursor": "Example cursor" } ``` ## Relationships - An Integration **connects** one [System](/business/nouns/system): an Integration connects an outside [Source](/business/nouns/source) to one [System](/business/nouns/system), with credentials at [Studio](/business/nouns/studio), [Startup](/business/nouns/startup) or [Customer](/business/nouns/customer) scope. `connects`, inverse [`connectedVia`](/business/nouns/system#rel-connected-via). ## Lifecycle | State | Meaning | Moves to | | --- | --- | --- | | `connecting` (first) | Waiting for the account holder to approve the outside account. | `connected` by [Integration.connect](/business/nouns/integration/connect); `revoked` by [Integration.revoke](/business/nouns/integration/revoke) | | `connected` | Calls and syncs run with a live token. | `needsReauth` by [Integration.refresh](/business/nouns/integration/refresh); `paused` by [Integration.pause](/business/nouns/integration/pause); `revoked` by [Integration.revoke](/business/nouns/integration/revoke) | | `needsReauth` | The upstream refused a refresh, so calls wait until the account holder approves again. | `connected` by [Integration.reconnect](/business/nouns/integration/reconnect); `revoked` by [Integration.revoke](/business/nouns/integration/revoke) | | `paused` | Every call stops, and the token and cursor are kept. | `connected` by [Integration.resume](/business/nouns/integration/resume); `revoked` by [Integration.revoke](/business/nouns/integration/revoke) | | `revoked` | Its token is revoked with the upstream; every record it brought in stays. | None: it ends here. | ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Integration.call](/business/nouns/integration/call) | Call sends one request to an upstream through an Integration, with its token filled in server-side, for endpoints no Mapping covers. | [Integration Engineer](/agents/engineering/integration-engineer) | [`Integration.called`](/business/events/Integration.called) | One-way (customer): `send`, `do` | | [Integration.connect](/business/nouns/integration/connect) | Connect asks an account holder to approve an outside account for one System and records the grants they approve. | [Integration Engineer](/agents/engineering/integration-engineer) | [`Integration.connected`](/business/events/Integration.connected) | Two-way: `try`, `send`, `do` | | [Integration.pause](/business/nouns/integration/pause) | Pause stops every call through an Integration at once and keeps its token and cursor. | [Worker](/business/nouns/worker) | [`Integration.paused`](/business/events/Integration.paused) | Two-way: `try`, `send`, `do` | | [Integration.reconnect](/business/nouns/integration/reconnect) | Reconnect re-approves an Integration in place, keeping its id and cursor, so nothing re-imports. | [Worker](/business/nouns/worker) | [`Integration.reconnected`](/business/events/Integration.reconnected) | Two-way: `try`, `send`, `do` | | [Integration.refresh](/business/nouns/integration/refresh) | Refresh renews an Integration’s outside token before it expires; a refused refresh moves it to `needsReauth`. | [Integration Engineer](/agents/engineering/integration-engineer) | [`Integration.refreshed`](/business/events/Integration.refreshed) | Two-way: `try`, `send`, `do` | | [Integration.resume](/business/nouns/integration/resume) | Resume restarts a paused Integration from its cursor and releases the Actions that waited on it. | [Worker](/business/nouns/worker) | [`Integration.resumed`](/business/events/Integration.resumed) | Two-way: `try`, `send`, `do` | | [Integration.revoke](/business/nouns/integration/revoke) | Revoke ends an Integration at once: its token is revoked with the upstream, and every record it brought in stays. | [Security Engineer](/agents/engineering/security-engineer) | [`Integration.revoked`](/business/events/Integration.revoked) | None. | | [Integration.sync](/business/nouns/integration/sync) | Sync exchanges records between a System and its connector, and the declared leader wins every conflict. | [Reliability Engineer](/agents/engineering/reliability-engineer) | [`Integration.synced`](/business/events/Integration.synced) | None. | | [Integration.create](/business/nouns/integration/create) | Creates an Integration. Inherited from [Noun](/business/nouns/noun). | None. | `Integration.created` | Two-way: `try`, `send`, `do` | | [Integration.get](/business/nouns/integration/get) | Returns one Integration by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Integration.list](/business/nouns/integration/list) | Returns Integrations, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Integration.update](/business/nouns/integration/update) | Changes the given properties of an Integration. Inherited from [Noun](/business/nouns/noun). | None. | `Integration.updated` | Two-way: `try`, `send`, `do` | | [Integration.delete](/business/nouns/integration/delete) | Deletes an Integration; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Integration.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Integration.create` | Yes | Yes | Yes | No | | `Integration.get` | Yes | Yes | Yes | Yes | | `Integration.list` | Yes | Yes | Yes | Yes | | `Integration.update` | Yes | Yes | Yes | No | | `Integration.delete` | Yes | Yes | Yes | No | | `Integration.call` | Yes | No | No | No | | `Integration.connect` | Yes | Yes | Yes | No | | `Integration.pause` | Yes | Yes | Yes | No | | `Integration.reconnect` | Yes | Yes | Yes | No | | `Integration.refresh` | Yes | Yes | Yes | No | | `Integration.resume` | Yes | Yes | Yes | No | | `Integration.revoke` | Yes | Yes | Yes | No | | `Integration.sync` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Sync the latest integration. ``` **API** ```bash curl -X POST https://api.sb/shiftnote.app/integrations/integration_1/sync \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/shiftnote.app", "integration": { "$id": "https://api.sb/shiftnote.app/integrations/integration_1", "$type": "Integration", "acquired": "owned", "scope": "studio", "mode": "mirror", "state": "connecting" }, "action": { "$id": "https://api.sb/shiftnote.app/actions/action_1", "operation": "Integration.sync", "status": "done" }, "links": { "self": "https://api.sb/shiftnote.app/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const integration = await $.Integration.sync({ integration: 'integration_1' }) ``` **CLI** ```bash npx startup-builder do Integration.sync --json '{"integration":"integration_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Integration.sync({ integration: 'integration_1' })" } } ``` ## Example A bookkeeping service connects each client's bank feed as an Integration at [Customer](/business/nouns/customer) scope. The feed syncs nightly into the client's own [Tenant](/business/nouns/tenant), and [db.sb](/code/platform/db-sb) stays the record. # pause URL: /business/nouns/integration/pause · Id: `verb:Integration.pause` · Call: `await $.Integration.pause({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Pause stops every call through an Integration at once and keeps its token and cursor. Pause stops every call through an [Integration](/business/nouns/integration) at once and keeps its token and cursor. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `integration` | [Integration](/business/nouns/integration) | Yes | The Integration to pause. | | `reason` | `text` | No | Why, shown to every Worker whose Action waits on it. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `integration` | [Integration](/business/nouns/integration) | Yes | The Integration, `paused`. | ## Effects - Emits [`Integration.paused`](/business/events/Integration.paused). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Holds every Action that needs it `pending` with reason `awaitingSource`. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Integration.pause](/business/nouns/integration/pause) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Pause the latest integration. ``` **API** ```bash curl -X POST https://api.sb/kilnbakery.com/integrations/integration_1/pause \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/kilnbakery.com", "integration": { "$id": "https://api.sb/kilnbakery.com/integrations/integration_1", "$type": "Integration", "acquired": "owned", "scope": "studio", "mode": "mirror", "state": "connecting" }, "action": { "$id": "https://api.sb/kilnbakery.com/actions/action_1", "operation": "Integration.pause", "status": "done" }, "links": { "self": "https://api.sb/kilnbakery.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const integration = await $.Integration.pause({ integration: 'integration_1' }) ``` **CLI** ```bash npx startup-builder do Integration.pause --json '{"integration":"integration_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Integration.pause({ integration: 'integration_1' })" } } ``` # reconnect URL: /business/nouns/integration/reconnect · Id: `verb:Integration.reconnect` · Call: `await $.Integration.reconnect({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Reconnect re-approves an Integration in place, keeping its id and cursor, so nothing re-imports. Reconnect re-approves an [Integration](/business/nouns/integration) in place, keeping its id and cursor, so nothing re-imports. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `integration` | [Integration](/business/nouns/integration) | Yes | The Integration in `needsReauth`. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `connectUrl` | `url` | Yes | The approval page; it expires in one hour. | | `integration` | [Integration](/business/nouns/integration) | Yes | The Integration, its id and cursor kept. | ## Effects - Emits [`Integration.reconnected`](/business/events/Integration.reconnected). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Resumes the Actions that waited on it, oldest first. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Integration.reconnect](/business/nouns/integration/reconnect) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Reconnect the latest integration. ``` **API** ```bash curl -X POST https://api.sb/ledgerlark.com/integrations/integration_1/reconnect \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/ledgerlark.com", "connectUrl": "https://ledgerlark.com", "integration": { "$id": "https://api.sb/ledgerlark.com/integrations/integration_1", "$type": "Integration", "acquired": "owned", "scope": "studio", "mode": "mirror", "state": "connecting" }, "action": { "$id": "https://api.sb/ledgerlark.com/actions/action_1", "operation": "Integration.reconnect", "status": "done" }, "links": { "self": "https://api.sb/ledgerlark.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { connectUrl, integration } = await $.Integration.reconnect({ integration: 'integration_1' }) ``` **CLI** ```bash npx startup-builder do Integration.reconnect --json '{"integration":"integration_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Integration.reconnect({ integration: 'integration_1' })" } } ``` # refresh URL: /business/nouns/integration/refresh · Id: `verb:Integration.refresh` · Call: `await $.Integration.refresh({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Refresh renews an Integration’s outside token before it expires; a refused refresh moves it to `needsReauth`. Refresh renews an [Integration](/business/nouns/integration)’s outside token before it expires; a refused refresh moves it to `needsReauth`. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `integration` | [Integration](/business/nouns/integration) | Yes | The Integration to refresh. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `integration` | [Integration](/business/nouns/integration) | Yes | The Integration with a new `refreshedAt`, or in `needsReauth`. | ## Effects - Emits [`Integration.refreshed`](/business/events/Integration.refreshed). - Performed by the [Integration Engineer](/agents/engineering/integration-engineer). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - On refusal, holds every Action that needs it `pending` with reason `awaitingSource`. - On refusal, opens a Task for the account holder with a reconnect link. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Integration.refresh](/business/nouns/integration/refresh) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Refresh the latest integration. ``` **API** ```bash curl -X POST https://api.sb/patentpad.com/integrations/integration_1/refresh \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/patentpad.com", "integration": { "$id": "https://api.sb/patentpad.com/integrations/integration_1", "$type": "Integration", "acquired": "owned", "scope": "studio", "mode": "mirror", "state": "connecting" }, "action": { "$id": "https://api.sb/patentpad.com/actions/action_1", "operation": "Integration.refresh", "status": "done" }, "links": { "self": "https://api.sb/patentpad.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const integration = await $.Integration.refresh({ integration: 'integration_1' }) ``` **CLI** ```bash npx startup-builder do Integration.refresh --json '{"integration":"integration_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Integration.refresh({ integration: 'integration_1' })" } } ``` # resume URL: /business/nouns/integration/resume · Id: `verb:Integration.resume` · Call: `await $.Integration.resume({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Resume restarts a paused Integration from its cursor and releases the Actions that waited on it. Resume restarts a paused [Integration](/business/nouns/integration) from its cursor and releases the [Actions](/business/nouns/action) that waited on it. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `integration` | [Integration](/business/nouns/integration) | Yes | The paused Integration. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `integration` | [Integration](/business/nouns/integration) | Yes | The Integration, `connected`. | ## Effects - Emits [`Integration.resumed`](/business/events/Integration.resumed). - Two-way: it runs at once, in the `try`, `send` and `do` modes. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Integration.resume](/business/nouns/integration/resume) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Resume the latest integration. ``` **API** ```bash curl -X POST https://api.sb/shiftnote.app/integrations/integration_1/resume \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/shiftnote.app", "integration": { "$id": "https://api.sb/shiftnote.app/integrations/integration_1", "$type": "Integration", "acquired": "owned", "scope": "studio", "mode": "mirror", "state": "connecting" }, "action": { "$id": "https://api.sb/shiftnote.app/actions/action_1", "operation": "Integration.resume", "status": "done" }, "links": { "self": "https://api.sb/shiftnote.app/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const integration = await $.Integration.resume({ integration: 'integration_1' }) ``` **CLI** ```bash npx startup-builder do Integration.resume --json '{"integration":"integration_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Integration.resume({ integration: 'integration_1' })" } } ``` # revoke URL: /business/nouns/integration/revoke · Id: `verb:Integration.revoke` · Call: `await $.Integration.revoke({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Revoke ends an Integration at once: its token is revoked with the upstream, and every record it brought in stays. Revoke ends an [Integration](/business/nouns/integration) at once: its token is revoked with the upstream, and every record it brought in stays. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `integration` | [Integration](/business/nouns/integration) | Yes | The Integration to end. | | `reason` | `text` | No | Why, kept on the Integration. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `integration` | [Integration](/business/nouns/integration) | Yes | The Integration, `revoked`. | ## Effects - Emits [`Integration.revoked`](/business/events/Integration.revoked). - Performed by the [Security Engineer](/agents/engineering/security-engineer). - Refuses the next call through it. - Ends every pending Action that needs it as `canceled`. - Stops mirroring; copies already written outside stay with their owner. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Integration.revoke](/business/nouns/integration/revoke) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Revoke the latest integration. ``` **API** ```bash curl -X POST https://api.sb/quietcopy.com/integrations/integration_1/revoke \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/quietcopy.com", "integration": { "$id": "https://api.sb/quietcopy.com/integrations/integration_1", "$type": "Integration", "acquired": "owned", "scope": "studio", "mode": "mirror", "state": "connecting" }, "action": { "$id": "https://api.sb/quietcopy.com/actions/action_1", "operation": "Integration.revoke", "status": "done" }, "links": { "self": "https://api.sb/quietcopy.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const integration = await $.Integration.revoke({ integration: 'integration_1' }) ``` **CLI** ```bash npx startup-builder do Integration.revoke --json '{"integration":"integration_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Integration.revoke({ integration: 'integration_1' })" } } ``` # sync URL: /business/nouns/integration/sync · Id: `verb:Integration.sync` · Call: `await $.Integration.sync({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Sync exchanges records between a System and its connector, and the declared leader wins every conflict. Sync exchanges records between a [System](/business/nouns/system) and its connector, and the declared leader wins every conflict. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `integration` | [Integration](/business/nouns/integration) | Yes | The connector to sync. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `integration` | [Integration](/business/nouns/integration) | Yes | The Integration with its sync cursor moved. | ## Effects - Emits [`Integration.synced`](/business/events/Integration.synced). - Performed by the [Reliability Engineer](/agents/engineering/reliability-engineer). - In `mirror`, an outside edit to a mirrored field is overwritten and recorded as an Action that ends `refused`. - In `import`, each outside edit becomes one Change or Action, checked like any other. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The request carries no key, or its key is expired or revoked. | [`unauthorized`](/code/api/errors/unauthorized) | Sign in again, or send a current key as a bearer token. | [Integration.sync](/business/nouns/integration/sync) | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Integration.sync](/business/nouns/integration/sync) | | The record is not in a state that allows this Verb, so the call is refused. | [`refused`](/code/api/errors/refused) | Read the record, run the Verb that moves it to an allowed state, then retry. | [Integration.sync](/business/nouns/integration/sync) | | The caller sent more requests than its rate allows. | [`rate-limited`](/code/api/errors/rate-limited) | Wait the number of seconds in the `Retry-After` header, then retry. | [Integration.sync](/business/nouns/integration/sync) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Sync the latest integration. ``` **API** ```bash curl -X POST https://api.sb/shiftnote.app/integrations/integration_1/sync \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/shiftnote.app", "integration": { "$id": "https://api.sb/shiftnote.app/integrations/integration_1", "$type": "Integration", "acquired": "owned", "scope": "studio", "mode": "mirror", "state": "connecting" }, "action": { "$id": "https://api.sb/shiftnote.app/actions/action_1", "operation": "Integration.sync", "status": "done" }, "links": { "self": "https://api.sb/shiftnote.app/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const integration = await $.Integration.sync({ integration: 'integration_1' }) ``` **CLI** ```bash npx startup-builder do Integration.sync --json '{"integration":"integration_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Integration.sync({ integration: 'integration_1' })" } } ``` Guides that call it: [Sell on AWS Marketplace](/products/offers/sell-on-aws-marketplace). # Interface URL: /business/nouns/interface · Id: `noun:interface` > An Interface is how a person or an Agent reaches a Product: an API, MCP server, CLI, SDK, Site, or App. An Interface is how a person or an [Agent](/business/nouns/agent) reaches a [Product](/business/nouns/product): an API, MCP server, CLI, SDK, [Site](/business/nouns/site), or [App](/business/nouns/app). ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `kind` | `string` | Yes | One of `api`, `mcp`, `cli`, `sdk`, `site`, `app`, `docs`, or `webhooks`. | | `path` | `string` | No | Where it is mounted on its Domain, such as `/api`. | | `conformsTo` | `json` | No | The Standards it also speaks, each mapping the Standard’s operations onto the Product’s Verbs. | ## Object ```json { "$id": "https://api.sb/patentpad.com/interfaces/interface_1", "$type": "Interface", "kind": "api", "path": "/", "conformsTo": { "standard": "openai-chat", "operations": { "chat.completions.create": "Listing.write" } } } ``` ## Relationships - An Interface **is mounted on** many [Domains](/business/nouns/domain): an Interface answers requests on the hostnames it is mounted on. `mountedOn`, inverse [`mounts`](/business/nouns/domain#rel-mounts). - An Interface **reaches** one [Product](/business/nouns/product): each Interface exposes one [Product](/business/nouns/product); a Product is reached through many Interfaces. `reaches`, inverse [`reachedVia`](/business/nouns/product#rel-reached-via). - An Interface **speaks** many [Standards](/business/nouns/standard): Callers in a [Standard](/business/nouns/standard)’s shape reach the Interface’s [Verbs](/business/nouns/verb) through the platform’s one translator for that Standard. `speaks`, inverse [`spokenBy`](/business/nouns/standard#rel-spoken-by). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Interface.create](/business/nouns/interface/create) | Creates an Interface. Inherited from [Noun](/business/nouns/noun). | None. | `Interface.created` | Two-way: `try`, `send`, `do` | | [Interface.get](/business/nouns/interface/get) | Returns one Interface by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Interface.list](/business/nouns/interface/list) | Returns Interfaces, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Interface.update](/business/nouns/interface/update) | Changes the given properties of an Interface. Inherited from [Noun](/business/nouns/noun). | None. | `Interface.updated` | Two-way: `try`, `send`, `do` | | [Interface.delete](/business/nouns/interface/delete) | Deletes an Interface; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Interface.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Interface.create` | Yes | Yes | Yes | No | | `Interface.get` | Yes | Yes | Yes | Yes | | `Interface.list` | Yes | Yes | Yes | Yes | | `Interface.update` | Yes | Yes | Yes | No | | `Interface.delete` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Add an interface to ShiftNote. ``` **API** ```bash curl -X POST https://api.sb/shiftnote.app/interfaces \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"kind":"api"}' ``` ```json { "api": "https://api.sb/shiftnote.app", "interface": { "$id": "https://api.sb/shiftnote.app/interfaces/interface_1", "$type": "Interface", "kind": "api" }, "action": { "$id": "https://api.sb/shiftnote.app/actions/action_1", "operation": "Interface.create", "status": "done" }, "links": { "self": "https://api.sb/shiftnote.app/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const result = await $.Interface.create({ kind: 'api' }) ``` **CLI** ```bash npx startup-builder do Interface.create --json '{"kind":"api"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Interface.create({ kind: 'api' })" } } ``` ## Example A currency-conversion [Product](/business/nouns/product) answers developers over the API, coding Agents as an MCP [Tool](/business/nouns/tool), operators from the CLI, and people on its pricing [Site](/business/nouns/site). # Interview URL: /business/nouns/interview · Id: `noun:interview` > An Interview is one person’s pass through a question script, led by an Agent, whose answers become Evidence. An Interview is one person’s pass through a question script, led by an [Agent](/business/nouns/agent), whose answers become [Evidence](/business/nouns/evidence). Its answers feed the [Story](/business/nouns/story) word for word. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `script` | [Template](/business/nouns/template) | Yes | The questions asked. | | `transcript` | `text` | No | What was said. |
Inherited from [Thread](/business/nouns/thread): 1 property | Property | Type | Required | Description | | --- | --- | --- | --- | | `subject` | `string` | No | What the Thread is about. |
## Object ```json { "$id": "https://api.sb/routewise.dev/interviews/interview_1", "$type": "Interview", "subject": "Example subject", "script": "template_1", "transcript": "Example transcript" } ``` ## Relationships - An Interview **is quoted in** many [Stories](/business/nouns/story): the Interviews whose words the [Story](/business/nouns/story) reuses. `quotedIn`, inverse [`quotes`](/business/nouns/story#rel-quotes). - An Interview **yields** many pieces of [Evidence](/business/nouns/evidence): an Interview captures quotes and commitments, each graded as [Evidence](/business/nouns/evidence). `yields`, inverse [`yieldedBy`](/business/nouns/evidence#rel-yielded-by). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Interview.create](/business/nouns/interview/create) | Creates an Interview. Inherited from [Noun](/business/nouns/noun). | None. | `Interview.created` | Two-way: `try`, `send`, `do` | | [Interview.get](/business/nouns/interview/get) | Returns one Interview by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Interview.list](/business/nouns/interview/list) | Returns Interviews, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | An Interview is kept forever and never edited: it has no `update` or `delete`. ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Interview.create` | Yes | Yes | Yes | No | | `Interview.get` | Yes | Yes | Yes | Yes | | `Interview.list` | Yes | Yes | Yes | Yes | ## Call it **Ask** ```text Add an interview to LedgerLark with a template. ``` **API** ```bash curl -X POST https://api.sb/ledgerlark.com/interviews \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"script":"template_1"}' ``` ```json { "api": "https://api.sb/ledgerlark.com", "interview": { "$id": "https://api.sb/ledgerlark.com/interviews/interview_1", "$type": "Interview", "script": "template_1" }, "action": { "$id": "https://api.sb/ledgerlark.com/actions/action_1", "operation": "Interview.create", "status": "done" }, "links": { "self": "https://api.sb/ledgerlark.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const interview = await $.Interview.create({ script: 'template_1' }) ``` **CLI** ```bash npx startup-builder do Interview.create --json '{"script":"template_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Interview.create({ script: 'template_1' })" } } ``` ## Example An Agent runs a five-question Interview with a music teacher about how she books lessons. Her answer, two lessons lost each week to text-message mixups, enters the `transcript` and becomes Evidence on the [Problem](/business/nouns/problem). # bill URL: /business/nouns/invoice/bill · Id: `verb:Invoice.bill` · Call: `await $.Invoice.bill({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Bill finalizes an Invoice and presents it to the Customer for payment. Bill finalizes an [Invoice](/business/nouns/invoice) and presents it to the [Customer](/business/nouns/customer) for payment. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `invoice` | [Invoice](/business/nouns/invoice) | Yes | The draft Invoice. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `invoice` | [Invoice](/business/nouns/invoice) | Yes | The open Invoice. | ## Effects - Emits [`Invoice.billed`](/business/events/Invoice.billed). - Performed by the [Billing Specialist](/agents/finance/billing-specialist). - One-way (customer): it waits out its delay window, and runs in the `send` and `do` modes. - Freezes the Invoice’s lines; a correction is a credit, never an edit. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Invoice.bill](/business/nouns/invoice/bill) | | The record is not in a state that allows this Verb, so the call is refused. | [`refused`](/code/api/errors/refused) | Read the record, run the Verb that moves it to an allowed state, then retry. | [Invoice.bill](/business/nouns/invoice/bill) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Medium: one-way, bounded (customer) | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | 1 business hour, in which a watcher can pause, redirect or cancel it; then it runs. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Bill the latest invoice. ``` **API** ```bash curl -X POST https://api.sb/tutorloop.com/invoices/invoice_1/bill \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/tutorloop.com", "invoice": { "$id": "https://api.sb/tutorloop.com/invoices/invoice_1", "$type": "Invoice", "total": { "amount": 60, "currency": "USD" }, "due": "2026-10-22" }, "action": { "$id": "https://api.sb/tutorloop.com/actions/action_1", "operation": "Invoice.bill", "status": "done" }, "links": { "self": "https://api.sb/tutorloop.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const invoice = await $.Invoice.bill({ invoice: 'invoice_1' }) ``` **CLI** ```bash npx startup-builder do Invoice.bill --json '{"invoice":"invoice_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Invoice.bill({ invoice: 'invoice_1' })" } } ``` Guides that call it: [Send an invoice](/systems/finance/send-an-invoice). # collect URL: /business/nouns/invoice/collect · Id: `verb:Invoice.collect` · Call: `await $.Invoice.collect({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Collect charges a Customer’s saved payment method for an open Invoice and retries on failure. Collect charges a [Customer](/business/nouns/customer)’s saved payment method for an open [Invoice](/business/nouns/invoice) and retries on failure. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `invoice` | [Invoice](/business/nouns/invoice) | Yes | The open Invoice. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `invoice` | [Invoice](/business/nouns/invoice) | Yes | The paid Invoice. | ## Effects - Emits [`Invoice.collected`](/business/events/Invoice.collected). - Performed by the [Billing Specialist](/agents/finance/billing-specialist). - One-way (money, customer): it waits out its delay window, and runs in the `send` and `do` modes. - Retries on the Startup’s retry schedule before the Invoice is marked uncollectible. - On a `send` Invoice, charges nothing: it records the Customer’s bank transfer when it reconciles and emits `Invoice.collected` then. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The operation is part of an Offer the caller has not accepted or paid for. | [`payment-required`](/code/api/errors/payment-required) | Accept the Offer named in the response, then retry the call. | [Offer.accept](/business/nouns/offer/accept) | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Invoice.collect](/business/nouns/invoice/collect) | | The record is not in a state that allows this Verb, so the call is refused. | [`refused`](/code/api/errors/refused) | Read the record, run the Verb that moves it to an allowed state, then retry. | [Invoice.collect](/business/nouns/invoice/collect) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Medium: one-way, bounded (money, customer) | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | 1 business hour, in which a watcher can pause, redirect or cancel it; then it runs. | | Limit | The spend [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) or [Mandate](/business/nouns/mandate) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Collect the latest invoice. ``` **API** ```bash curl -X POST https://api.sb/routewise.dev/invoices/invoice_1/collect \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/routewise.dev", "invoice": { "$id": "https://api.sb/routewise.dev/invoices/invoice_1", "$type": "Invoice", "total": { "amount": 25, "currency": "USD" }, "due": "2026-10-22" }, "action": { "$id": "https://api.sb/routewise.dev/actions/action_1", "operation": "Invoice.collect", "status": "done" }, "links": { "self": "https://api.sb/routewise.dev/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const invoice = await $.Invoice.collect({ invoice: 'invoice_1' }) ``` **CLI** ```bash npx startup-builder do Invoice.collect --json '{"invoice":"invoice_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Invoice.collect({ invoice: 'invoice_1' })" } } ``` Guides that call it: [Retry the payments that failed](/systems/finance/retry-failed-payments). # Invoice URL: /business/nouns/invoice · Id: `noun:invoice` > An Invoice is what a Customer owes for one or more Offers over one billing period. An Invoice is what a [Customer](/business/nouns/customer) owes for one or more [Offers](/business/nouns/offer) over one billing period. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `total` | `money` | Yes | The amount due. | | `due` | `date` | Yes | When payment is due. | | `paidAt` | `datetime` | No | When it was paid. | | `status` | `string` | No | One of `draft`, `open`, `paid`, `void`, or `uncollectible`. | | `collection` | `string` | No | `charge` charges the saved payment method; `send` sends the Invoice and waits for a transfer. `charge` by default. | | `terms` | `integer` | No | Days from issue until a `send` Invoice is due, such as 30; sets `due`. | | `purchaseOrder` | `string` | No | The Customer’s purchase order number, printed on the Invoice. | | `refunded` | `money` | No | The total returned to the Customer, from zero up to the amount paid. | | `number` | `string` | No | The Invoice number, sequential per Startup and never reused, voided Invoices included. | | `lines` | `json` | No | Each Offer billed: its quantity, Period and amount, with any Coupon or Credit Grant applied. | | `pdf` | `url` | No | The Invoice, or its receipt once paid, as a PDF on the Startup’s Domain that names the seller of record. | | `payUrl` | `url` | No | The page on the Startup’s Domain where the Customer pays it by card or bank transfer. | ## Object ```json { "$id": "https://api.sb/patentpad.com/invoices/invoice_1", "$type": "Invoice", "total": { "amount": 499, "currency": "USD" }, "due": "2026-10-22", "paidAt": "2026-10-22T12:00:00Z", "status": "draft", "collection": "charge", "terms": 1, "purchaseOrder": "PO-48213", "refunded": { "amount": 499, "currency": "USD" }, "number": "LEDG-0042", "lines": {}, "pdf": "https://patentpad.com", "payUrl": "https://patentpad.com" } ``` ## Relationships - An Invoice **is billed for** one [Subscription](/business/nouns/subscription): the Invoices the [Subscription](/business/nouns/subscription) issues, one for each period it renews. `billedFor`, inverse [`bills`](/business/nouns/subscription#rel-bills). - An Invoice **charges** one [Customer](/business/nouns/customer): each Invoice is owed by one [Customer](/business/nouns/customer). `charges`, inverse [`invoices`](/business/nouns/customer#rel-invoices). - An Invoice **has** many [Credit Grants](/business/nouns/credit-grant): the Invoices the grant paid toward when they finalized. `creditGrants`, inverse [`offsets`](/business/nouns/credit-grant#rel-offsets). ## Lifecycle | State | Meaning | Moves to | | --- | --- | --- | | `draft` (first) | Its lines can still change, and the Customer has not seen it. | `open` by [Invoice.bill](/business/nouns/invoice/bill); `void` by [Invoice.void](/business/nouns/invoice/void) | | `open` | Finalized and presented to the Customer, its lines frozen. | `paid` by [Invoice.collect](/business/nouns/invoice/collect); `void` by [Invoice.void](/business/nouns/invoice/void); `uncollectible` on [`Invoice.overdue`](/business/nouns/invoice#invoiceoverdue) when every retry on the Startup’s retry schedule has failed | | `paid` | Paid in full; a refund adds to its refunded total and never reopens it. | None: it ends here. | | `void` | Canceled unpaid and kept on record, with its reversing Entries posted. | None: it ends here. | | `uncollectible` | Kept on record as unpaid once every retry has failed. | None: it ends here. | ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Invoice.bill](/business/nouns/invoice/bill) | Bill finalizes an Invoice and presents it to the Customer for payment. | [Billing Specialist](/agents/finance/billing-specialist) | [`Invoice.billed`](/business/events/Invoice.billed) | One-way (customer): `send`, `do` | | [Invoice.collect](/business/nouns/invoice/collect) | Collect charges a Customer’s saved payment method for an open Invoice and retries on failure. | [Billing Specialist](/agents/finance/billing-specialist) | [`Invoice.collected`](/business/events/Invoice.collected) | One-way (money, customer): `send`, `do` | | [Invoice.refund](/business/nouns/invoice/refund) | Refund returns all or part of a paid Invoice to the Customer’s original payment method and posts the reversing Entries. | [Billing Specialist](/agents/finance/billing-specialist) | [`Invoice.refunded`](/business/events/Invoice.refunded) | One-way (money, customer): `send`, `do` | | [Invoice.void](/business/nouns/invoice/void) | Void cancels an unpaid Invoice, keeps it on record, and posts the reversing Entries. | [Billing Specialist](/agents/finance/billing-specialist) | [`Invoice.voided`](/business/events/Invoice.voided) | One-way (money, customer): `send`, `do` | | [Invoice.create](/business/nouns/invoice/create) | Creates an Invoice. Inherited from [Noun](/business/nouns/noun). | None. | `Invoice.created` | Two-way: `try`, `send`, `do` | | [Invoice.get](/business/nouns/invoice/get) | Returns one Invoice by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Invoice.list](/business/nouns/invoice/list) | Returns Invoices, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Invoice.update](/business/nouns/invoice/update) | Changes the given properties of an Invoice. Inherited from [Noun](/business/nouns/noun). | None. | `Invoice.updated` | Two-way: `try`, `send`, `do` | An Invoice is never deleted: it ends by [Invoice.void](/business/nouns/invoice/void), and its records stay. ## Events Events no Verb emits. Each Verb’s Event is in the Verbs table above; every Event is delivered in the same shape. ### Invoice.overdue An open Invoice passed its `due` date unpaid, or a retry on the Startup’s retry schedule failed. Raised by a clock. | Field | Type | Required | Description | | --- | --- | --- | --- | | `name` | `string` | Yes | `Invoice.overdue`. | | `at` | `datetime` | Yes | When it happened. | | `seq` | `integer` | No | Its position in the namespace, one more than the Event before; any seq is a cursor into the history. | | `data` | `json` | Yes | The Thing as the Action left it. | | `data.invoice` | [Invoice](/business/nouns/invoice) | Yes | The Invoice as the change left it. | | `data.invoice.total` | `money` | Yes | The amount due. | | `data.invoice.due` | `date` | Yes | When payment is due. | | `data.invoice.paidAt` | `datetime` | No | When it was paid. | | `data.invoice.status` | `string` | No | One of `draft`, `open`, `paid`, `void`, or `uncollectible`. | | `data.invoice.collection` | `string` | No | `charge` charges the saved payment method; `send` sends the Invoice and waits for a transfer. `charge` by default. | | `data.invoice.terms` | `integer` | No | Days from issue until a `send` Invoice is due, such as 30; sets `due`. | | `data.invoice.purchaseOrder` | `string` | No | The Customer’s purchase order number, printed on the Invoice. | | `data.invoice.refunded` | `money` | No | The total returned to the Customer, from zero up to the amount paid. | | `data.invoice.number` | `string` | No | The Invoice number, sequential per Startup and never reused, voided Invoices included. | | `data.invoice.lines` | `json` | No | Each Offer billed: its quantity, Period and amount, with any Coupon or Credit Grant applied. | | `data.invoice.pdf` | `url` | No | The Invoice, or its receipt once paid, as a PDF on the Startup’s Domain that names the seller of record. | | `data.invoice.payUrl` | `url` | No | The page on the Startup’s Domain where the Customer pays it by card or bank transfer. | | `data.attempt` | `integer` | Yes | Which retry failed; 0 when the due date passed. | | `data.nextRetryAt` | `datetime` | No | When the next retry runs; empty after the last one. | ```json { "$id": "https://api.sb/patentpad.com/events/event_1", "$type": "Event", "name": "Invoice.overdue", "at": "2026-10-22T12:00:00Z", "data": { "invoice": { "$id": "https://api.sb/patentpad.com/invoices/invoice_1", "$type": "Invoice", "total": { "amount": 499, "currency": "USD" }, "due": "2026-10-22", "paidAt": "2026-10-22T12:00:00Z", "status": "open", "collection": "charge", "terms": 1, "purchaseOrder": "PO-48213", "refunded": { "amount": 499, "currency": "USD" }, "number": "LEDG-0042", "lines": {}, "pdf": "https://patentpad.com", "payUrl": "https://patentpad.com" }, "attempt": 1, "nextRetryAt": "2026-10-22T12:00:00Z" }, "seq": 1 } ``` ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Invoice.create` | Yes | Yes | Yes | No | | `Invoice.get` | Yes | Yes | Yes | Yes | | `Invoice.list` | Yes | Yes | Yes | Yes | | `Invoice.update` | Yes | Yes | Yes | No | | `Invoice.bill` | Yes | No | No | No | | `Invoice.collect` | Yes | No | No | No | | `Invoice.refund` | Yes | No | No | No | | `Invoice.void` | Yes | No | No | No | ## Stripe **Invoice** (`invoice`). The source of truth is db.sb, and Stripe holds a copy written from it. | Property | Stripe field | Source of truth | | --- | --- | --- | | `total` | `total` | db.sb | | `due` | `due_date` | db.sb | | `status` | `status` | Stripe | | `paidAt` | `status_transitions.paid_at` | Stripe | | `collection` | `collection_method` | db.sb | | `terms` | `days_until_due` | db.sb | | `number` | `number` | db.sb | | `lines` | `lines.data` | db.sb | | State | Stripe status | | --- | --- | | `draft` | `draft` | | `open` | `open` | | `paid` | `paid` | | `void` | `void` | | `uncollectible` | `uncollectible` | ## Call it **Ask** ```text Bill the latest invoice. ``` **API** ```bash curl -X POST https://api.sb/tutorloop.com/invoices/invoice_1/bill \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/tutorloop.com", "invoice": { "$id": "https://api.sb/tutorloop.com/invoices/invoice_1", "$type": "Invoice", "total": { "amount": 60, "currency": "USD" }, "due": "2026-10-22" }, "action": { "$id": "https://api.sb/tutorloop.com/actions/action_1", "operation": "Invoice.bill", "status": "done" }, "links": { "self": "https://api.sb/tutorloop.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const invoice = await $.Invoice.bill({ invoice: 'invoice_1' }) ``` **CLI** ```bash npx startup-builder do Invoice.bill --json '{"invoice":"invoice_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Invoice.bill({ invoice: 'invoice_1' })" } } ``` ## Example The monthly Invoice to a dental group bills $99 for the base plan and $36 for 1,200 reminders over its [Limit](/business/nouns/limit). It is due in 15 days. # refund URL: /business/nouns/invoice/refund · Id: `verb:Invoice.refund` · Call: `await $.Invoice.refund({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Refund returns all or part of a paid Invoice to the Customer’s original payment method and posts the reversing Entries. Refund returns all or part of a paid [Invoice](/business/nouns/invoice) to the [Customer](/business/nouns/customer)’s original payment method and posts the reversing [Entries](/business/nouns/entry). ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `invoice` | [Invoice](/business/nouns/invoice) | Yes | The paid Invoice. | | `amount` | `money` | No | The amount. Defaults to the full payment; pro rata takes the unused part of the Period. | | `reason` | `text` | Yes | Why the money goes back, kept on the Invoice. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `invoice` | [Invoice](/business/nouns/invoice) | Yes | The Invoice, with its refunded amount. | ## Effects - Emits [`Invoice.refunded`](/business/events/Invoice.refunded). - Performed by the [Billing Specialist](/agents/finance/billing-specialist). - One-way (money, customer): it waits out its delay window, and runs in the `send` and `do` modes. - Checks the refund Limit; above it, opens an Approval for the Finance Lead and the Action waits. - Waits the refund delay window before the money moves. - Refuses while a Dispute on the Invoice is open. - Returns money to the original payment only, never to a balance. - Adds the amount to the Invoice’s refunded total. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Invoice.refund](/business/nouns/invoice/refund) | | A Dispute on the Invoice is open | [`refused`](/code/api/errors/refused) | Clear what the check names, then call it again. | [Invoice.refund](/business/nouns/invoice/refund) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Medium: one-way, bounded (money, customer) | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | 1 business hour, in which a watcher can pause, redirect or cancel it; then it runs. | | Limit | The spend [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) or [Mandate](/business/nouns/mandate) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Finance Lead](/agents/finance/finance-lead). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Refund the latest invoice. ``` **API** ```bash curl -X POST https://api.sb/patentpad.com/invoices/invoice_1/refund \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"reason":"Example reason"}' ``` ```json { "api": "https://api.sb/patentpad.com", "invoice": { "$id": "https://api.sb/patentpad.com/invoices/invoice_1", "$type": "Invoice", "total": { "amount": 499, "currency": "USD" }, "due": "2026-10-22" }, "action": { "$id": "https://api.sb/patentpad.com/actions/action_1", "operation": "Invoice.refund", "status": "done" }, "links": { "self": "https://api.sb/patentpad.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const invoice = await $.Invoice.refund({ invoice: 'invoice_1', reason: 'Example reason' }) ``` **CLI** ```bash npx startup-builder do Invoice.refund --json '{"invoice":"invoice_1","reason":"Example reason"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Invoice.refund({ invoice: 'invoice_1', reason: 'Example reason' })" } } ``` # void URL: /business/nouns/invoice/void · Id: `verb:Invoice.void` · Call: `await $.Invoice.void({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Void cancels an unpaid Invoice, keeps it on record, and posts the reversing Entries. Void cancels an unpaid [Invoice](/business/nouns/invoice), keeps it on record, and posts the reversing [Entries](/business/nouns/entry). ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `invoice` | [Invoice](/business/nouns/invoice) | Yes | The unpaid Invoice. | | `reason` | `text` | Yes | Why the amount is no longer due. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `invoice` | [Invoice](/business/nouns/invoice) | Yes | The voided Invoice, kept forever. | ## Effects - Emits [`Invoice.voided`](/business/events/Invoice.voided). - Performed by the [Billing Specialist](/agents/finance/billing-specialist). - One-way (money, customer): it waits out its delay window, and runs in the `send` and `do` modes. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Invoice.void](/business/nouns/invoice/void) | | The record changed since it was read, so the write would overwrite a newer version. | [`conflict`](/code/api/errors/conflict) | Read the record again, then retry the write against its current state. | [Invoice.void](/business/nouns/invoice/void) | | The record is not in a state that allows this Verb, so the call is refused. | [`refused`](/code/api/errors/refused) | Read the record, run the Verb that moves it to an allowed state, then retry. | [Invoice.void](/business/nouns/invoice/void) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Medium: one-way, bounded (money, customer) | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | 1 business hour, in which a watcher can pause, redirect or cancel it; then it runs. | | Limit | The spend [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) or [Mandate](/business/nouns/mandate) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Void the latest invoice. ``` **API** ```bash curl -X POST https://api.sb/routewise.dev/invoices/invoice_1/void \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"reason":"Example reason"}' ``` ```json { "api": "https://api.sb/routewise.dev", "invoice": { "$id": "https://api.sb/routewise.dev/invoices/invoice_1", "$type": "Invoice", "total": { "amount": 25, "currency": "USD" }, "due": "2026-10-22" }, "action": { "$id": "https://api.sb/routewise.dev/actions/action_1", "operation": "Invoice.void", "status": "done" }, "links": { "self": "https://api.sb/routewise.dev/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const invoice = await $.Invoice.void({ invoice: 'invoice_1', reason: 'Example reason' }) ``` **CLI** ```bash npx startup-builder do Invoice.void --json '{"invoice":"invoice_1","reason":"Example reason"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Invoice.void({ invoice: 'invoice_1', reason: 'Example reason' })" } } ``` # estimate URL: /business/nouns/issue/estimate · Id: `verb:Issue.estimate` · Call: `await $.Issue.estimate({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Estimate records the effort an Issue needs, in days, so a week holds only what fits. Estimate records the effort an [Issue](/business/nouns/issue) needs, in days, so a week holds only what fits. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `issue` | [Issue](/business/nouns/issue) | Yes | The Issue to size. | | `days` | `number` | Yes | The effort in working days. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `issue` | [Issue](/business/nouns/issue) | Yes | The estimated Issue. | ## Effects - Emits [`Issue.estimated`](/business/events/Issue.estimated). - Performed by the [Engineering Lead](/agents/engineering/engineering-lead). - Two-way: it runs at once, in the `try`, `send` and `do` modes. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Issue.estimate](/business/nouns/issue/estimate) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Estimate the latest issue. ``` **API** ```bash curl -X POST https://api.sb/routewise.dev/issues/issue_1/estimate \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"days":1}' ``` ```json { "api": "https://api.sb/routewise.dev", "issue": { "$id": "https://api.sb/routewise.dev/issues/issue_1", "$type": "Issue", "status": "pending", "mode": "try" }, "action": { "$id": "https://api.sb/routewise.dev/actions/action_1", "operation": "Issue.estimate", "status": "done" }, "links": { "self": "https://api.sb/routewise.dev/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const issue = await $.Issue.estimate({ issue: 'issue_1', days: 1 }) ``` **CLI** ```bash npx startup-builder do Issue.estimate --json '{"issue":"issue_1","days":1}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Issue.estimate({ issue: 'issue_1', days: 1 })" } } ``` # Issue URL: /business/nouns/issue · Id: `noun:issue` > An Issue is a Task reporting a problem or request, such as a bug or a feature request, with a reporter and a triage step. An Issue is a [Task](/business/nouns/task) reporting a problem or request, such as a bug or a feature request, with a reporter and a triage step. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `kind` | `string` | No | One of `bug`, `request`, or `question`. | | `severity` | `string` | No | Set by triage; a vulnerability takes `critical`, `high`, `medium` or `low`, which sets `due`. An Incident keeps its own scale. | | `advisory` | `string` | No | For a vulnerability: the public advisory it matches, with the affected package and range. |
Inherited from [Task](/business/nouns/task): 3 properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `due` | `datetime` | No | When the Task is due. | | `priority` | `integer` | No | Its rank in the inbox, highest first. | | `recurrence` | `string` | No | The schedule a recurring duty repeats on. |
Inherited from [Action](/business/nouns/action): 11 properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `status` | `string` | Yes | One of `pending`, `done`, `failed`, `canceled`, or `refused`. | | `reason` | `string` | No | Why a pending Action waits: `queued`, `running`, `retrying`, `awaitingWorker`, `awaitingInput`, `awaitingSource`, `awaitingAction`, or `awaitingTime`. | | `mode` | `string` | Yes | How the caller invoked it: `try`, `send`, or `do`. | | `by` | [Worker](/business/nouns/worker) | No | The Worker that performed it. | | `for` | [Party](/business/nouns/party) | No | The Party it was done on behalf of. | | `via` | `string` | No | The Interface or request it arrived through. | | `on` | `string` | No | The Action or Event that caused it, such as the failed attempt a retry follows. | | `thing` | `string` | No | The record, at the Version the Action was decided against. | | `input` | `json` | No | The input it was called with. | | `createdAt` | `datetime` | No | When it was called. | | `reserved` | `money` | No | The most this Action may cost, held against its Limits from the check until it settles, billed misses included. |
## Object ```json { "$id": "https://api.sb/patentpad.com/issues/issue_1", "$type": "Issue", "status": "pending", "reason": "queued", "mode": "try", "by": "worker_1", "for": "party_1", "via": "API", "on": "Invoice.overdue", "thing": "invoice_1@v3", "input": {}, "createdAt": "2026-10-22T12:00:00Z", "reserved": { "amount": 499, "currency": "USD" }, "due": "2026-10-22T12:00:00Z", "priority": 1, "recurrence": "Weekly on Friday", "kind": "bug", "severity": "critical", "advisory": "GHSA-xxxx-xxxx-xxxx" } ``` ## Relationships - An Issue **addresses** many [Problems](/business/nouns/problem): an Issue addresses the [Problems](/business/nouns/problem) its [Evidence](/business/nouns/evidence) came from, so the [Customers](/business/nouns/customer) behind that Evidence hear when it ships. `addresses`, inverse [`addressedBy`](/business/nouns/problem#rel-addressed-by). - An Issue **has** many [Conversations](/business/nouns/conversation): the Issue or [Incident](/business/nouns/incident) a [Conversation](/business/nouns/conversation) reports; resolving it answers every linked Conversation. `conversations`, inverse [`reports`](/business/nouns/conversation#rel-reports). - An Issue **reports** one [Thing](/business/nouns/thing): an Issue is about one [Thing](/business/nouns/thing), such as a [Product](/business/nouns/product), a [Page](/business/nouns/page), or an [Order](/business/nouns/order). `reports`, inverse [`issues`](/business/nouns/thing#rel-issues). - An Issue **is resolved by** many [Changes](/business/nouns/change): a [Change](/business/nouns/change) names the Issues it fixes; each resolves when the last open Change naming it reaches all traffic. `resolvedBy`, inverse [`resolves`](/business/nouns/change#rel-resolves). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Issue.estimate](/business/nouns/issue/estimate) | Estimate records the effort an Issue needs, in days, so a week holds only what fits. | [Engineering Lead](/agents/engineering/engineering-lead) | [`Issue.estimated`](/business/events/Issue.estimated) | Two-way: `try`, `send`, `do` | | [Issue.reopen](/business/nouns/issue/reopen) | Reopen returns a resolved Issue to its owning Role when the fix does not hold. | [Product Lead](/agents/product/product-lead) | [`Issue.reopened`](/business/events/Issue.reopened) | None. | | [Issue.resolve](/business/nouns/issue/resolve) | Resolve closes an Issue with its fix recorded and tells every Customer who reported it. | [Product Lead](/agents/product/product-lead) | [`Issue.resolved`](/business/events/Issue.resolved) | None. | | [Issue.schedule](/business/nouns/issue/schedule) | Schedule commits an Issue to a week of work and records each scope change after the week starts. | [Product Lead](/agents/product/product-lead) | [`Issue.scheduled`](/business/events/Issue.scheduled) | Two-way: `try`, `send`, `do` | | [Issue.triage](/business/nouns/issue/triage) | Triage sets an Issue’s severity and owning Role from its content and the Customer it affects. | [Product Lead](/agents/product/product-lead) | [`Issue.triaged`](/business/events/Issue.triaged) | None. | | [Issue.create](/business/nouns/issue/create) | Creates an Issue. Inherited from [Noun](/business/nouns/noun). | None. | `Issue.created` | Two-way: `try`, `send`, `do` | | [Issue.get](/business/nouns/issue/get) | Returns one Issue by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Issue.list](/business/nouns/issue/list) | Returns Issues, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Issue.update](/business/nouns/issue/update) | Changes the given properties of an Issue. Inherited from [Noun](/business/nouns/noun). | None. | `Issue.updated` | Two-way: `try`, `send`, `do` | | [Issue.delete](/business/nouns/issue/delete) | Deletes an Issue; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Issue.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Issue.create` | Yes | Yes | Yes | No | | `Issue.get` | Yes | Yes | Yes | Yes | | `Issue.list` | Yes | Yes | Yes | Yes | | `Issue.update` | Yes | Yes | Yes | No | | `Issue.delete` | Yes | Yes | Yes | No | | `Issue.estimate` | Yes | Yes | Yes | No | | `Issue.reopen` | Yes | Yes | Yes | No | | `Issue.resolve` | Yes | Yes | Yes | No | | `Issue.schedule` | Yes | Yes | Yes | No | | `Issue.triage` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Triage the latest issue. ``` **API** ```bash curl -X POST https://api.sb/ledgerlark.com/issues/issue_1/triage \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/ledgerlark.com", "issue": { "$id": "https://api.sb/ledgerlark.com/issues/issue_1", "$type": "Issue", "status": "pending", "mode": "try" }, "action": { "$id": "https://api.sb/ledgerlark.com/actions/action_1", "operation": "Issue.triage", "status": "done" }, "links": { "self": "https://api.sb/ledgerlark.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const issue = await $.Issue.triage({ issue: 'issue_1' }) ``` **CLI** ```bash npx startup-builder do Issue.triage --json '{"issue":"issue_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Issue.triage({ issue: 'issue_1' })" } } ``` ## Example A translator reports that the drafting [Agent](/business/nouns/agent) drops accents from proper names. The Issue records the reporter, a sample document, and its triage outcome: bug. # reopen URL: /business/nouns/issue/reopen · Id: `verb:Issue.reopen` · Call: `await $.Issue.reopen({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Reopen returns a resolved Issue to its owning Role when the fix does not hold. Reopen returns a resolved [Issue](/business/nouns/issue) to its owning [Role](/business/nouns/role) when the fix does not hold. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `issue` | [Issue](/business/nouns/issue) | Yes | The resolved Issue. | | `reason` | `text` | Yes | What still fails. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `issue` | [Issue](/business/nouns/issue) | Yes | The reopened Issue. | ## Effects - Emits [`Issue.reopened`](/business/events/Issue.reopened). - Performed by the [Product Lead](/agents/product/product-lead). ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Issue.reopen](/business/nouns/issue/reopen) | | The record is not in a state that allows this Verb, so the call is refused. | [`refused`](/code/api/errors/refused) | Read the record, run the Verb that moves it to an allowed state, then retry. | [Issue.reopen](/business/nouns/issue/reopen) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Reopen the latest issue. ``` **API** ```bash curl -X POST https://api.sb/tutorloop.com/issues/issue_1/reopen \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"reason":"Example reason"}' ``` ```json { "api": "https://api.sb/tutorloop.com", "issue": { "$id": "https://api.sb/tutorloop.com/issues/issue_1", "$type": "Issue", "status": "pending", "mode": "try" }, "action": { "$id": "https://api.sb/tutorloop.com/actions/action_1", "operation": "Issue.reopen", "status": "done" }, "links": { "self": "https://api.sb/tutorloop.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const issue = await $.Issue.reopen({ issue: 'issue_1', reason: 'Example reason' }) ``` **CLI** ```bash npx startup-builder do Issue.reopen --json '{"issue":"issue_1","reason":"Example reason"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Issue.reopen({ issue: 'issue_1', reason: 'Example reason' })" } } ``` # resolve URL: /business/nouns/issue/resolve · Id: `verb:Issue.resolve` · Call: `await $.Issue.resolve({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Resolve closes an Issue with its fix recorded and tells every Customer who reported it. Resolve closes an [Issue](/business/nouns/issue) with its fix recorded and tells every [Customer](/business/nouns/customer) who reported it. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `issue` | [Issue](/business/nouns/issue) | Yes | The Issue to close. | | `resolution` | `text` | Yes | What fixed it. | | `change` | [Change](/business/nouns/change) | No | The Change whose full rollout fixed the Issue; its Version is recorded as the resolution. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `issue` | [Issue](/business/nouns/issue) | Yes | The resolved Issue. | ## Effects - Emits [`Issue.resolved`](/business/events/Issue.resolved). - Performed by the [Product Lead](/agents/product/product-lead). - Answers every Conversation that reports the Issue, each in its own Channel, with what changed. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Issue.resolve](/business/nouns/issue/resolve) | | The record is not in a state that allows this Verb, so the call is refused. | [`refused`](/code/api/errors/refused) | Read the record, run the Verb that moves it to an allowed state, then retry. | [Issue.resolve](/business/nouns/issue/resolve) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Resolve the latest issue. ``` **API** ```bash curl -X POST https://api.sb/ledgerlark.com/issues/issue_1/resolve \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"resolution":"Example resolution"}' ``` ```json { "api": "https://api.sb/ledgerlark.com", "issue": { "$id": "https://api.sb/ledgerlark.com/issues/issue_1", "$type": "Issue", "status": "pending", "mode": "try" }, "action": { "$id": "https://api.sb/ledgerlark.com/actions/action_1", "operation": "Issue.resolve", "status": "done" }, "links": { "self": "https://api.sb/ledgerlark.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const issue = await $.Issue.resolve({ issue: 'issue_1', resolution: 'Example resolution' }) ``` **CLI** ```bash npx startup-builder do Issue.resolve --json '{"issue":"issue_1","resolution":"Example resolution"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Issue.resolve({ issue: 'issue_1', resolution: 'Example resolution' })" } } ``` # schedule URL: /business/nouns/issue/schedule · Id: `verb:Issue.schedule` · Call: `await $.Issue.schedule({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Schedule commits an Issue to a week of work and records each scope change after the week starts. Schedule commits an [Issue](/business/nouns/issue) to a week of work and records each scope change after the week starts. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `issue` | [Issue](/business/nouns/issue) | Yes | The Issue to commit. | | `week` | `date` | Yes | The first day of the week it is committed to. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `issue` | [Issue](/business/nouns/issue) | Yes | The scheduled Issue. | ## Effects - Emits [`Issue.scheduled`](/business/events/Issue.scheduled). - Performed by the [Product Lead](/agents/product/product-lead). - Two-way: it runs at once, in the `try`, `send` and `do` modes. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Issue.schedule](/business/nouns/issue/schedule) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Schedule the latest issue. ``` **API** ```bash curl -X POST https://api.sb/quietcopy.com/issues/issue_1/schedule \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"week":"2026-10-22"}' ``` ```json { "api": "https://api.sb/quietcopy.com", "issue": { "$id": "https://api.sb/quietcopy.com/issues/issue_1", "$type": "Issue", "status": "pending", "mode": "try" }, "action": { "$id": "https://api.sb/quietcopy.com/actions/action_1", "operation": "Issue.schedule", "status": "done" }, "links": { "self": "https://api.sb/quietcopy.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const issue = await $.Issue.schedule({ issue: 'issue_1', week: '2026-10-22' }) ``` **CLI** ```bash npx startup-builder do Issue.schedule --json '{"issue":"issue_1","week":"2026-10-22"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Issue.schedule({ issue: 'issue_1', week: '2026-10-22' })" } } ``` # triage URL: /business/nouns/issue/triage · Id: `verb:Issue.triage` · Call: `await $.Issue.triage({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Triage sets an Issue’s severity and owning Role from its content and the Customer it affects. Triage sets an [Issue](/business/nouns/issue)’s severity and owning [Role](/business/nouns/role) from its content and the [Customer](/business/nouns/customer) it affects. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `issue` | [Issue](/business/nouns/issue) | Yes | The new Issue. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `issue` | [Issue](/business/nouns/issue) | Yes | The triaged Issue. | ## Effects - Emits [`Issue.triaged`](/business/events/Issue.triaged). - Performed by the [Product Lead](/agents/product/product-lead). - For a vulnerability, sets `due` from the Startup’s severity deadlines. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Issue.triage](/business/nouns/issue/triage) | | The record is not in a state that allows this Verb, so the call is refused. | [`refused`](/code/api/errors/refused) | Read the record, run the Verb that moves it to an allowed state, then retry. | [Issue.triage](/business/nouns/issue/triage) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Triage the latest issue. ``` **API** ```bash curl -X POST https://api.sb/ledgerlark.com/issues/issue_1/triage \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/ledgerlark.com", "issue": { "$id": "https://api.sb/ledgerlark.com/issues/issue_1", "$type": "Issue", "status": "pending", "mode": "try" }, "action": { "$id": "https://api.sb/ledgerlark.com/actions/action_1", "operation": "Issue.triage", "status": "done" }, "links": { "self": "https://api.sb/ledgerlark.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const issue = await $.Issue.triage({ issue: 'issue_1' }) ``` **CLI** ```bash npx startup-builder do Issue.triage --json '{"issue":"issue_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Issue.triage({ issue: 'issue_1' })" } } ``` # Key Result URL: /business/nouns/key-result · Id: `noun:key-result` > A Key Result is one measurable target inside a Goal: a Metric, a baseline, a target, and a deadline. A Key Result is one measurable target inside a [Goal](/business/nouns/goal): a [Metric](/business/nouns/metric), a baseline, a target, and a deadline. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `baseline` | `number` | Yes | Where the Metric started. | | `target` | `number` | Yes | Where the Metric must reach. | | `deadline` | `date` | Yes | When it must reach it. | ## Object ```json { "$id": "https://api.sb/ledgerlark.com/key-results/key_result_1", "$type": "KeyResult", "baseline": 1, "target": 1, "deadline": "2026-10-22" } ``` ## Relationships - A Key Result **measures** one [Goal](/business/nouns/goal): a [Goal](/business/nouns/goal) is met when its Key Results reach their targets. `measures`, inverse [`keyResults`](/business/nouns/goal#rel-key-results). - A Key Result **reads** one [Metric](/business/nouns/metric): a Key Result compares one [Metric](/business/nouns/metric)’s value against its baseline and target. `reads`, inverse [`readBy`](/business/nouns/metric#rel-read-by). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [KeyResult.create](/business/nouns/key-result/create) | Creates a Key Result. Inherited from [Noun](/business/nouns/noun). | None. | `KeyResult.created` | Two-way: `try`, `send`, `do` | | [KeyResult.get](/business/nouns/key-result/get) | Returns one Key Result by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [KeyResult.list](/business/nouns/key-result/list) | Returns Key Results, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [KeyResult.update](/business/nouns/key-result/update) | Changes the given properties of a Key Result. Inherited from [Noun](/business/nouns/noun). | None. | `KeyResult.updated` | Two-way: `try`, `send`, `do` | | [KeyResult.delete](/business/nouns/key-result/delete) | Deletes a Key Result; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `KeyResult.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `KeyResult.create` | Yes | Yes | Yes | No | | `KeyResult.get` | Yes | Yes | Yes | Yes | | `KeyResult.list` | Yes | Yes | Yes | Yes | | `KeyResult.update` | Yes | Yes | Yes | No | | `KeyResult.delete` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Add a key result to Kiln Bakery. ``` **API** ```bash curl -X POST https://api.sb/kilnbakery.com/key-results \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"baseline":1,"target":1,"deadline":"2026-10-22"}' ``` ```json { "api": "https://api.sb/kilnbakery.com", "keyResult": { "$id": "https://api.sb/kilnbakery.com/key-results/key_result_1", "$type": "KeyResult", "baseline": 1, "target": 1, "deadline": "2026-10-22" }, "action": { "$id": "https://api.sb/kilnbakery.com/actions/action_1", "operation": "KeyResult.create", "status": "done" }, "links": { "self": "https://api.sb/kilnbakery.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const keyResult = await $.KeyResult.create({ baseline: 1, target: 1, deadline: '2026-10-22' }) ``` **CLI** ```bash npx startup-builder do KeyResult.create --json '{"baseline":1,"target":1,"deadline":"2026-10-22"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.KeyResult.create({ baseline: 1, target: 1, deadline: '2026-10-22' })" } } ``` ## Example A Key Result of a clinic-reminder [SaaS](/products/templates/saas) reads the paid clinic count [Metric](/business/nouns/metric) from 35 to a target of 200 by year end. # Keyword URL: /business/nouns/keyword · Id: `noun:keyword` > A Keyword is a search phrase or AI prompt that Pages target, with its rank and citations observed over time. A Keyword is a search phrase or AI prompt that [Pages](/business/nouns/page) target, with its rank and citations observed over time. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `phrase` | `string` | Yes | The words searched or asked. | | `form` | `string` | No | One of `search` or `question`. | ## Object ```json { "$id": "https://api.sb/routewise.dev/keywords/keyword_1", "$type": "Keyword", "phrase": "Example phrase", "form": "search" } ``` ## Relationships - A Keyword **is targeted by** many [Pages](/business/nouns/page): a [Page](/business/nouns/page) is written to rank for, or be cited on, its Keywords. `targetedBy`, inverse [`targets`](/business/nouns/page#rel-targets). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Keyword.measure](/business/nouns/keyword/measure) | Measure records a Keyword’s monthly search volume, difficulty, cost per click and trend in one locale. | [Analyst](/agents/marketing/analyst) | [`Keyword.measured`](/business/events/Keyword.measured) | Two-way: `try`, `send`, `do` | | [Keyword.create](/business/nouns/keyword/create) | Creates a Keyword. Inherited from [Noun](/business/nouns/noun). | None. | `Keyword.created` | Two-way: `try`, `send`, `do` | | [Keyword.get](/business/nouns/keyword/get) | Returns one Keyword by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Keyword.list](/business/nouns/keyword/list) | Returns Keywords, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Keyword.update](/business/nouns/keyword/update) | Changes the given properties of a Keyword. Inherited from [Noun](/business/nouns/noun). | None. | `Keyword.updated` | Two-way: `try`, `send`, `do` | | [Keyword.delete](/business/nouns/keyword/delete) | Deletes a Keyword; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Keyword.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Keyword.create` | Yes | Yes | Yes | No | | `Keyword.get` | Yes | Yes | Yes | Yes | | `Keyword.list` | Yes | Yes | Yes | Yes | | `Keyword.update` | Yes | Yes | Yes | No | | `Keyword.delete` | Yes | Yes | Yes | No | | `Keyword.measure` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Measure the latest keyword. ``` **API** ```bash curl -X POST https://api.sb/ledgerlark.com/keywords/keyword_1/measure \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/ledgerlark.com", "keyword": { "$id": "https://api.sb/ledgerlark.com/keywords/keyword_1", "$type": "Keyword", "phrase": "Example phrase" }, "action": { "$id": "https://api.sb/ledgerlark.com/actions/action_1", "operation": "Keyword.measure", "status": "done" }, "links": { "self": "https://api.sb/ledgerlark.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const keyword = await $.Keyword.measure({ keyword: 'keyword_1' }) ``` **CLI** ```bash npx startup-builder do Keyword.measure --json '{"keyword":"keyword_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Keyword.measure({ keyword: 'keyword_1' })" } } ``` ## Example The Keyword "home inspector near me" is targeted by the city [Pages](/business/nouns/page) of an inspector directory. Its largest city Page ranks third and is cited in one AI answer this week. # measure URL: /business/nouns/keyword/measure · Id: `verb:Keyword.measure` · Call: `await $.Keyword.measure({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Measure records a Keyword’s monthly search volume, difficulty, cost per click and trend in one locale. Measure records a [Keyword](/business/nouns/keyword)’s monthly search volume, difficulty, cost per click and trend in one locale. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `keyword` | [Keyword](/business/nouns/keyword) | Yes | The Keyword to measure. | | `locale` | `string` | No | The market and language, such as `en-US`. Defaults to the Startup’s home Market. | | `venue` | `string` | No | The search venue, such as `google-search`. Defaults to the largest one in the Market. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `keyword` | [Keyword](/business/nouns/keyword) | Yes | The Keyword; each measure is a `Keyword.measured` Event with its method and observation time. | ## Effects - Emits [`Keyword.measured`](/business/events/Keyword.measured). - Performed by the [Analyst](/agents/marketing/analyst). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Returns a measurement younger than the `marketData.maxAge` Setting instead of measuring again. - Shares measurements across every Startup that targets the same phrase and locale. - Records method and Cost on the Action; the measurement itself is never edited. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Keyword.measure](/business/nouns/keyword/measure) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Measure the latest keyword. ``` **API** ```bash curl -X POST https://api.sb/ledgerlark.com/keywords/keyword_1/measure \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/ledgerlark.com", "keyword": { "$id": "https://api.sb/ledgerlark.com/keywords/keyword_1", "$type": "Keyword", "phrase": "Example phrase" }, "action": { "$id": "https://api.sb/ledgerlark.com/actions/action_1", "operation": "Keyword.measure", "status": "done" }, "links": { "self": "https://api.sb/ledgerlark.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const keyword = await $.Keyword.measure({ keyword: 'keyword_1' }) ``` **CLI** ```bash npx startup-builder do Keyword.measure --json '{"keyword":"keyword_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Keyword.measure({ keyword: 'keyword_1' })" } } ``` # assign URL: /business/nouns/lead/assign · Id: `verb:Lead.assign` · Call: `await $.Lead.assign({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Assign gives a Lead one owner Worker, by round robin, territory or ICP fit, as the Startup’s routing Policy says. Assign gives a [Lead](/business/nouns/lead) one owner [Worker](/business/nouns/worker), by round robin, territory or [ICP](/business/nouns/icp) fit, as the [Startup](/business/nouns/startup)’s routing [Policy](/business/nouns/policy) says. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `lead` | [Lead](/business/nouns/lead) | Yes | The Lead to route. | | `owner` | [Worker](/business/nouns/worker) | No | The Worker to own it; omitted, the routing Policy picks. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `lead` | [Lead](/business/nouns/lead) | Yes | The Lead, with its owner. | ## Effects - Emits [`Lead.assigned`](/business/events/Lead.assigned). - Performed by the [Sales Lead](/agents/sales/sales-lead). - Two-way: it runs at once, in the `try`, `send` and `do` modes. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Lead.assign](/business/nouns/lead/assign) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Assign the latest lead. ``` **API** ```bash curl -X POST https://api.sb/ledgerlark.com/leads/lead_1/assign \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/ledgerlark.com", "lead": { "$id": "https://api.sb/ledgerlark.com/leads/lead_1", "$type": "Lead", "status": "new" }, "action": { "$id": "https://api.sb/ledgerlark.com/actions/action_1", "operation": "Lead.assign", "status": "done" }, "links": { "self": "https://api.sb/ledgerlark.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const lead = await $.Lead.assign({ lead: 'lead_1' }) ``` **CLI** ```bash npx startup-builder do Lead.assign --json '{"lead":"lead_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Lead.assign({ lead: 'lead_1' })" } } ``` # convert URL: /business/nouns/lead/convert · Id: `verb:Lead.convert` · Call: `await $.Lead.convert({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Convert ends a qualified Lead’s pursuit as a Lead: it opens a Deal or routes the Lead to self-serve checkout. Convert ends a qualified [Lead](/business/nouns/lead)’s pursuit as a Lead: it opens a [Deal](/business/nouns/deal) or routes the Lead to self-serve checkout. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `lead` | [Lead](/business/nouns/lead) | Yes | The qualified Lead. | | `offer` | [Offer](/business/nouns/offer) | Yes | The Offer the Deal pursues, or the checkout sells. | | `route` | `string` | Yes | Where the Lead goes: `deal` for an assisted sale or `checkout` for self-serve. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `deal` | [Deal](/business/nouns/deal) | No | The opened Deal, when the route is `deal`. | | `lead` | [Lead](/business/nouns/lead) | Yes | The Lead, now converted. | ## Effects - Emits [`Lead.converted`](/business/events/Lead.converted). - Performed by the [Sales Lead](/agents/sales/sales-lead). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Moves the Lead to `converted` and keeps its Acquisition on the Deal and the later Customer. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Lead.convert](/business/nouns/lead/convert) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Convert the latest lead with an offer. ``` **API** ```bash curl -X POST https://api.sb/shiftnote.app/leads/lead_1/convert \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"offer":"offer_1","route":"Example route"}' ``` ```json { "api": "https://api.sb/shiftnote.app", "deal": { "$id": "https://api.sb/shiftnote.app/deals/deal_1", "$type": "Deal", "status": "Open" }, "lead": { "$id": "https://api.sb/shiftnote.app/leads/lead_1", "$type": "Lead", "status": "converted" }, "action": { "$id": "https://api.sb/shiftnote.app/actions/action_1", "operation": "Lead.convert", "status": "done" }, "links": { "self": "https://api.sb/shiftnote.app/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { deal, lead } = await $.Lead.convert({ lead: 'lead_1', offer: 'offer_1', route: 'Example route' }) ``` **CLI** ```bash npx startup-builder do Lead.convert --json '{"lead":"lead_1","offer":"offer_1","route":"Example route"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Lead.convert({ lead: 'lead_1', offer: 'offer_1', route: 'Example route' })" } } ``` # disqualify URL: /business/nouns/lead/disqualify · Id: `verb:Lead.disqualify` · Call: `await $.Lead.disqualify({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Disqualify ends a Lead’s pursuit because it fits no Offer, with the reason; its Contact record and Consent stay. Disqualify ends a [Lead](/business/nouns/lead)’s pursuit because it fits no [Offer](/business/nouns/offer), with the reason; its [Contact](/business/nouns/contact) record and [Consent](/business/nouns/consent) stay. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `lead` | [Lead](/business/nouns/lead) | Yes | The Lead to disqualify. | | `reason` | `string` | Yes | Why it fits no Offer. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `lead` | [Lead](/business/nouns/lead) | Yes | The Lead, now `disqualified`. | ## Effects - Emits [`Lead.disqualified`](/business/events/Lead.disqualified). - Performed by the [Sales Lead](/agents/sales/sales-lead). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - The Lead fit Policy reads the reason when it grades the next Lead. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Lead.disqualify](/business/nouns/lead/disqualify) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Disqualify the latest lead. ``` **API** ```bash curl -X POST https://api.sb/patentpad.com/leads/lead_1/disqualify \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"reason":"noFit"}' ``` ```json { "api": "https://api.sb/patentpad.com", "lead": { "$id": "https://api.sb/patentpad.com/leads/lead_1", "$type": "Lead", "status": "disqualified" }, "action": { "$id": "https://api.sb/patentpad.com/actions/action_1", "operation": "Lead.disqualify", "status": "done" }, "links": { "self": "https://api.sb/patentpad.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const lead = await $.Lead.disqualify({ lead: 'lead_1', reason: 'noFit' }) ``` **CLI** ```bash npx startup-builder do Lead.disqualify --json '{"lead":"lead_1","reason":"noFit"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Lead.disqualify({ lead: 'lead_1', reason: 'noFit' })" } } ``` # Lead URL: /business/nouns/lead · Id: `noun:lead` > A Lead is a Contact who raised a hand, by joining a Waitlist, filling a Form, or replying, without accepting an Offer. A Lead is a [Contact](/business/nouns/contact) who raised a hand, by joining a [Waitlist](/business/nouns/waitlist), filling a [Form](/business/nouns/form), or replying, without accepting an [Offer](/business/nouns/offer). Accepting an Offer, at any [Price](/business/nouns/price), makes a Lead a [Customer](/business/nouns/customer). ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `interest` | `text` | No | What the Lead asked for. | | `status` | `string` | Yes | One of `new`, `working`, `nurture`, `converted`, or `disqualified`. | | `owner` | [Worker](/business/nouns/worker) | No | The Worker who answers it. | | `fit` | `string` | No | One of `strong`, `partial`, or `none`: fit to the ICP as the Lead fit Policy grades it, never set by hand. |
Inherited from [Contact](/business/nouns/contact): 3 properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `email` | `email` | No | The primary email address. | | `phone` | `string` | No | The primary phone number. | | `name` | `string` | No | The name the Contact goes by. |
## Object ```json { "$id": "https://api.sb/quietcopy.com/leads/lead_1", "$type": "Lead", "email": "mei@quietcopy.com", "phone": "Example phone", "name": "QuietCopy", "interest": "Example interest", "status": "new", "owner": "worker_1", "fit": "strong" } ``` ## Relationships - A Lead **is acquired by** one [Acquisition](/business/nouns/acquisition): each Lead keeps the [Acquisition](/business/nouns/acquisition) that first brought it, through either door: a [Visit](/business/nouns/visit) or an outbound reply. `acquiredBy`, inverse [`leads`](/business/nouns/acquisition#rel-leads). - A Lead **is captured by** one [Form](/business/nouns/form): each [Form](/business/nouns/form) submission creates a Lead. `capturedBy`, inverse [`captures`](/business/nouns/form#rel-captures). - A Lead **is converted from** one [Prospect](/business/nouns/prospect): a [Prospect](/business/nouns/prospect) becomes a Lead on first engaging, such as a reply or a [Form](/business/nouns/form) submission. `convertedFrom`, inverse [`convertsTo`](/business/nouns/prospect#rel-converts-to). - A Lead **identifies** many [Visitors](/business/nouns/visitor): a Lead, once it gives an address, is tied to every [Visitor](/business/nouns/visitor) id it used, one per device. `identifies`, inverse [`identifiedAs`](/business/nouns/visitor#rel-identified-as). - A Lead **is referred by** one [Referral](/business/nouns/referral): each [Referral](/business/nouns/referral) sends one Lead to the [Startup](/business/nouns/startup). `referredBy`, inverse [`refers`](/business/nouns/referral#rel-refers). - A Lead **waits on** one [Waitlist](/business/nouns/waitlist): Leads wait on a [Waitlist](/business/nouns/waitlist) in the order its [Setting](/business/nouns/setting) ranks them. `waitsOn`, inverse [`holds`](/business/nouns/waitlist#rel-holds). ## Lifecycle | State | Meaning | Moves to | | --- | --- | --- | | `new` (first) | It raised a hand, and no Worker works it yet. | `working` by [Lead.assign](/business/nouns/lead/assign); `nurture` by [Lead.nurture](/business/nouns/lead/nurture); `disqualified` by [Lead.disqualify](/business/nouns/lead/disqualify); `converted` on [`Offer.accepted`](/business/events/Offer.accepted) when the Lead buys on its own | | `working` | Its owner is in touch and owes the next step. | `converted` by [Lead.qualify](/business/nouns/lead/qualify); `converted` by [Lead.convert](/business/nouns/lead/convert); `nurture` by [Lead.nurture](/business/nouns/lead/nurture); `disqualified` by [Lead.disqualify](/business/nouns/lead/disqualify) | | `nurture` | Not ready to buy: it is off its owner’s queue and hears from a Sequence until it raises a hand again. | `working` by [Lead.assign](/business/nouns/lead/assign); `disqualified` by [Lead.disqualify](/business/nouns/lead/disqualify) | | `converted` | It fits an Offer: a Deal is open for it, or it bought on its own; the Customer record carries on. | None: it ends here. | | `disqualified` | It fits no Offer, for the reason recorded; its Contact record stays. | None: it ends here. | ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Lead.assign](/business/nouns/lead/assign) | Assign gives a Lead one owner Worker, by round robin, territory or ICP fit, as the Startup’s routing Policy says. | [Sales Lead](/agents/sales/sales-lead) | [`Lead.assigned`](/business/events/Lead.assigned) | Two-way: `try`, `send`, `do` | | [Lead.convert](/business/nouns/lead/convert) | Convert ends a qualified Lead’s pursuit as a Lead: it opens a Deal or routes the Lead to self-serve checkout. | [Sales Lead](/agents/sales/sales-lead) | [`Lead.converted`](/business/events/Lead.converted) | Two-way: `try`, `send`, `do` | | [Lead.disqualify](/business/nouns/lead/disqualify) | Disqualify ends a Lead’s pursuit because it fits no Offer, with the reason; its Contact record and Consent stay. | [Sales Lead](/agents/sales/sales-lead) | [`Lead.disqualified`](/business/events/Lead.disqualified) | Two-way: `try`, `send`, `do` | | [Waitlist.join](/business/nouns/waitlist/join) | Join adds a Lead to a Waitlist for an Offer that is not open to them. | [Marketing Lead](/agents/marketing/marketing-lead) | [`Waitlist.joined`](/business/events/Waitlist.joined) | None. | | [Lead.nurture](/business/nouns/lead/nurture) | Nurture takes a Lead that is not ready to buy off its owner’s queue and onto a Sequence, until it raises a hand again. | [Sales Lead](/agents/sales/sales-lead) | [`Lead.nurtured`](/business/events/Lead.nurtured) | Two-way: `try`, `send`, `do` | | [Lead.qualify](/business/nouns/lead/qualify) | Qualify confirms a Lead matches an Offer’s ICP and opens a Deal for it. | [Sales Engineer](/agents/sales/sales-engineer) | [`Lead.qualified`](/business/events/Lead.qualified) | None. | | [Lead.create](/business/nouns/lead/create) | Creates a Lead. Inherited from [Noun](/business/nouns/noun). | None. | `Lead.created` | Two-way: `try`, `send`, `do` | | [Lead.get](/business/nouns/lead/get) | Returns one Lead by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Lead.list](/business/nouns/lead/list) | Returns Leads, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Lead.update](/business/nouns/lead/update) | Changes the given properties of a Lead. Inherited from [Noun](/business/nouns/noun). | None. | `Lead.updated` | Two-way: `try`, `send`, `do` | | [Lead.delete](/business/nouns/lead/delete) | Deletes a Lead; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Lead.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Lead.create` | Yes | Yes | Yes | No | | `Lead.get` | Yes | Yes | Yes | Yes | | `Lead.list` | Yes | Yes | Yes | Yes | | `Lead.update` | Yes | Yes | Yes | No | | `Lead.delete` | Yes | Yes | Yes | No | | `Lead.assign` | Yes | Yes | Yes | No | | `Lead.convert` | Yes | Yes | Yes | No | | `Lead.disqualify` | Yes | Yes | Yes | No | | `Lead.nurture` | Yes | Yes | Yes | No | | `Lead.qualify` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Qualify the latest lead with an offer. ``` **API** ```bash curl -X POST https://api.sb/shiftnote.app/leads/lead_1/qualify \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"offer":"offer_1"}' ``` ```json { "api": "https://api.sb/shiftnote.app", "deal": { "$id": "https://api.sb/shiftnote.app/deals/deal_1", "$type": "Deal", "status": "Open" }, "lead": { "$id": "https://api.sb/shiftnote.app/leads/lead_1", "$type": "Lead", "status": "new" }, "action": { "$id": "https://api.sb/shiftnote.app/actions/action_1", "operation": "Lead.qualify", "status": "done" }, "links": { "self": "https://api.sb/shiftnote.app/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { deal, lead } = await $.Lead.qualify({ lead: 'lead_1', offer: 'offer_1' }) ``` **CLI** ```bash npx startup-builder do Lead.qualify --json '{"lead":"lead_1","offer":"offer_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Lead.qualify({ lead: 'lead_1', offer: 'offer_1' })" } } ``` ## Example A music teacher joins the Waitlist for a lesson-booking [App](/business/nouns/app) and becomes a Lead, with `interest` set to "group lessons". She becomes a Customer when she accepts an Offer. # nurture URL: /business/nouns/lead/nurture · Id: `verb:Lead.nurture` · Call: `await $.Lead.nurture({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Nurture takes a Lead that is not ready to buy off its owner’s queue and onto a Sequence, until it raises a hand again. Nurture takes a [Lead](/business/nouns/lead) that is not ready to buy off its owner’s queue and onto a [Sequence](/business/nouns/sequence), until it raises a hand again. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `lead` | [Lead](/business/nouns/lead) | Yes | The Lead to nurture. | | `sequence` | [Sequence](/business/nouns/sequence) | No | The Sequence to enroll it in. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `lead` | [Lead](/business/nouns/lead) | Yes | The Lead, now in `nurture`. | ## Effects - Emits [`Lead.nurtured`](/business/events/Lead.nurtured). - Performed by the [Sales Lead](/agents/sales/sales-lead). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Enrolls the Lead in the Sequence when one is given. - Its next reply or form puts it back on a queue through `Lead.assign`. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Lead.nurture](/business/nouns/lead/nurture) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Nurture the latest lead. ``` **API** ```bash curl -X POST https://api.sb/shiftnote.app/leads/lead_1/nurture \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/shiftnote.app", "lead": { "$id": "https://api.sb/shiftnote.app/leads/lead_1", "$type": "Lead", "status": "new" }, "action": { "$id": "https://api.sb/shiftnote.app/actions/action_1", "operation": "Lead.nurture", "status": "done" }, "links": { "self": "https://api.sb/shiftnote.app/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const lead = await $.Lead.nurture({ lead: 'lead_1' }) ``` **CLI** ```bash npx startup-builder do Lead.nurture --json '{"lead":"lead_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Lead.nurture({ lead: 'lead_1' })" } } ``` # qualify URL: /business/nouns/lead/qualify · Id: `verb:Lead.qualify` · Call: `await $.Lead.qualify({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Qualify confirms a Lead matches an Offer’s ICP and opens a Deal for it. Qualify confirms a [Lead](/business/nouns/lead) matches an [Offer](/business/nouns/offer)’s [ICP](/business/nouns/icp) and opens a [Deal](/business/nouns/deal) for it. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `lead` | [Lead](/business/nouns/lead) | Yes | The Lead to qualify. | | `offer` | [Offer](/business/nouns/offer) | Yes | The Offer whose ICP the Lead matches. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `deal` | [Deal](/business/nouns/deal) | Yes | The open Deal. | | `lead` | [Lead](/business/nouns/lead) | Yes | The Lead, now qualified. | ## Effects - Emits [`Lead.qualified`](/business/events/Lead.qualified). - Performed by the [Sales Engineer](/agents/sales/sales-engineer). ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Lead.qualify](/business/nouns/lead/qualify) | | The record is not in a state that allows this Verb, so the call is refused. | [`refused`](/code/api/errors/refused) | Read the record, run the Verb that moves it to an allowed state, then retry. | [Lead.qualify](/business/nouns/lead/qualify) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Qualify the latest lead with an offer. ``` **API** ```bash curl -X POST https://api.sb/shiftnote.app/leads/lead_1/qualify \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"offer":"offer_1"}' ``` ```json { "api": "https://api.sb/shiftnote.app", "deal": { "$id": "https://api.sb/shiftnote.app/deals/deal_1", "$type": "Deal", "status": "Open" }, "lead": { "$id": "https://api.sb/shiftnote.app/leads/lead_1", "$type": "Lead", "status": "new" }, "action": { "$id": "https://api.sb/shiftnote.app/actions/action_1", "operation": "Lead.qualify", "status": "done" }, "links": { "self": "https://api.sb/shiftnote.app/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { deal, lead } = await $.Lead.qualify({ lead: 'lead_1', offer: 'offer_1' }) ``` **CLI** ```bash npx startup-builder do Lead.qualify --json '{"lead":"lead_1","offer":"offer_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Lead.qualify({ lead: 'lead_1', offer: 'offer_1' })" } } ``` Next: [`Meeting.book`](/business/nouns/meeting/book) (in `guide:qualify-leads-and-book-demos`). Guides that call it: [Qualify leads and book demos](/workflows/guides/qualify-leads-and-book-demos). # Lifecycle URL: /business/nouns/lifecycle · Id: `noun:lifecycle` > A Lifecycle is the states a Thing of one Noun moves through and the Verbs that move it between them. A Lifecycle is the states a [Thing](/business/nouns/thing) of one [Noun](/business/nouns/noun) moves through and the [Verbs](/business/nouns/verb) that move it between them. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `states` | `string[]` | Yes | The states, in order. | | `initial` | `string` | Yes | The state a new Thing starts in. | ## Object ```json { "$id": "https://api.sb/quietcopy.com/lifecycles/lifecycle_1", "$type": "Lifecycle", "states": [ "Example states" ], "initial": "Example initial" } ``` ## Relationships - A Lifecycle **governs** one [Noun](/business/nouns/noun): a [Noun](/business/nouns/noun)’s Lifecycle lists the states its [Things](/business/nouns/thing) move through and the [Verbs](/business/nouns/verb) that move them. `governs`, inverse [`movesThrough`](/business/nouns/noun#rel-moves-through). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Lifecycle.get](/business/nouns/lifecycle/get) | Returns one Lifecycle by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Lifecycle.list](/business/nouns/lifecycle/list) | Returns Lifecycles, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Lifecycle.update](/business/nouns/lifecycle/update) | Changes the given properties of a Lifecycle. Inherited from [Noun](/business/nouns/noun). | None. | `Lifecycle.updated` | Two-way: `try`, `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Lifecycle.get` | Yes | Yes | Yes | Yes | | `Lifecycle.list` | Yes | Yes | Yes | Yes | | `Lifecycle.update` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Show me the latest lifecycle. ``` **API** ```bash curl https://api.sb/petpantry.shop/lifecycles/lifecycle_1 \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/petpantry.shop", "$type": "Lifecycle", "$id": "https://api.sb/petpantry.shop/lifecycles/lifecycle_1", "lifecycle": { "$id": "https://api.sb/petpantry.shop/lifecycles/lifecycle_1", "$type": "Lifecycle", "states": [ "Example states" ], "initial": "Example initial" }, "links": { "self": "https://api.sb/petpantry.shop/lifecycles/lifecycle_1", "up": "https://api.sb/petpantry.shop/lifecycles" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const lifecycle = await $.Lifecycle.get({ id: 'lifecycle_1' }) ``` **CLI** ```bash npx startup-builder do Lifecycle.get --json '{"id":"lifecycle_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Lifecycle.get({ id: 'lifecycle_1' })" } } ``` ## Example The [Order](/business/nouns/order) Lifecycle runs placed, paid, fulfilled, closed. The Verb `pay` moves an Order from placed to paid. # Limit URL: /business/nouns/limit · Id: `noun:limit` > A Limit is a bound on a Permission, Entitlement, or Mandate, checked before every call; exceeding it creates an Approval. A Limit is a bound on a [Permission](/business/nouns/permission), [Entitlement](/business/nouns/entitlement), or [Mandate](/business/nouns/mandate), checked before every call; exceeding it creates an [Approval](/business/nouns/approval). ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `amount` | `money` | No | The most money it allows. | | `count` | `integer` | No | The most calls or units it allows. | | `period` | `string` | No | The window a rate resets over, such as a month. | | `percent` | `number` | No | The largest share off a reference amount it allows, such as 15 percent off list Price. | | `resets` | `string` | No | One of `calendar`, `rolling`: a calendar Limit resets at the start of each period, a rolling one counts the last period from now. | ## Object ```json { "$id": "https://api.sb/routewise.dev/limits/limit_1", "$type": "Limit", "amount": { "amount": 25, "currency": "USD" }, "count": 1, "period": "Example period", "percent": 1, "resets": "calendar" } ``` ## Relationships None. ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Limit.raise](/business/nouns/limit/raise) | Raise lifts a Limit after an Approval allows it, and the Action that waited on it proceeds. | [Founder](/agents/founding/founder) | [`Limit.raised`](/business/events/Limit.raised) | One-way (money): `send`, `do` | | [Limit.create](/business/nouns/limit/create) | Creates a Limit. Inherited from [Noun](/business/nouns/noun). | None. | `Limit.created` | Two-way: `try`, `send`, `do` | | [Limit.get](/business/nouns/limit/get) | Returns one Limit by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Limit.list](/business/nouns/limit/list) | Returns Limits, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Limit.update](/business/nouns/limit/update) | Changes the given properties of a Limit. Inherited from [Noun](/business/nouns/noun). | None. | `Limit.updated` | Two-way: `try`, `send`, `do` | | [Limit.delete](/business/nouns/limit/delete) | Deletes a Limit; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Limit.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Limit.create` | Yes | Yes | No | No | | `Limit.get` | Yes | Yes | Yes | Yes | | `Limit.list` | Yes | Yes | Yes | Yes | | `Limit.update` | Yes | Yes | No | No | | `Limit.delete` | Yes | Yes | No | No | | `Limit.raise` | Yes | No | No | No | ## Call it **Ask** ```text Raise the latest limit. ``` **API** ```bash curl -X POST https://api.sb/ledgerlark.com/limits/limit_1/raise \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"to":{}}' ``` ```json { "api": "https://api.sb/ledgerlark.com", "limit": { "$id": "https://api.sb/ledgerlark.com/limits/limit_1", "$type": "Limit", "amount": { "amount": 400, "currency": "USD" }, "count": 1 }, "action": { "$id": "https://api.sb/ledgerlark.com/actions/action_1", "operation": "Limit.raise", "status": "done" }, "links": { "self": "https://api.sb/ledgerlark.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const limit = await $.Limit.raise({ limit: 'limit_1', to: {} }) ``` **CLI** ```bash npx startup-builder do Limit.raise --json '{"limit":"limit_1","to":{}}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Limit.raise({ limit: 'limit_1', to: {} })" } } ``` ## Example The [Billing Specialist](/agents/finance/billing-specialist)'s refund Limit is $100. A $250 refund stops before it runs and opens an [Approval](/business/nouns/approval). # raise URL: /business/nouns/limit/raise · Id: `verb:Limit.raise` · Call: `await $.Limit.raise({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Raise lifts a Limit after an Approval allows it, and the Action that waited on it proceeds. Raise lifts a [Limit](/business/nouns/limit) after an [Approval](/business/nouns/approval) allows it, and the [Action](/business/nouns/action) that waited on it proceeds. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `limit` | [Limit](/business/nouns/limit) | Yes | The Limit to lift. | | `to` | `json` | Yes | The new amount, count or rate. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `limit` | [Limit](/business/nouns/limit) | Yes | The raised Limit. | ## Effects - Emits [`Limit.raised`](/business/events/Limit.raised). - Performed by the [Founder](/agents/founding/founder). - One-way (money): it waits out its delay window, and runs in the `send` and `do` modes. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Limit.raise](/business/nouns/limit/raise) | | The record is not in a state that allows this Verb, so the call is refused. | [`refused`](/code/api/errors/refused) | Read the record, run the Verb that moves it to an allowed state, then retry. | [Limit.raise](/business/nouns/limit/raise) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Medium: one-way, bounded (money) | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | 1 business hour, in which a watcher can pause, redirect or cancel it; then it runs. | | Limit | The spend [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) or [Mandate](/business/nouns/mandate) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Raise the latest limit. ``` **API** ```bash curl -X POST https://api.sb/ledgerlark.com/limits/limit_1/raise \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"to":{}}' ``` ```json { "api": "https://api.sb/ledgerlark.com", "limit": { "$id": "https://api.sb/ledgerlark.com/limits/limit_1", "$type": "Limit", "amount": { "amount": 400, "currency": "USD" }, "count": 1 }, "action": { "$id": "https://api.sb/ledgerlark.com/actions/action_1", "operation": "Limit.raise", "status": "done" }, "links": { "self": "https://api.sb/ledgerlark.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const limit = await $.Limit.raise({ limit: 'limit_1', to: {} }) ``` **CLI** ```bash npx startup-builder do Limit.raise --json '{"limit":"limit_1","to":{}}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Limit.raise({ limit: 'limit_1', to: {} })" } } ``` # Mailbox URL: /business/nouns/mailbox · Id: `noun:mailbox` > A Mailbox is an email Channel at a Domain, held by a Startup, a Role, or a Worker, so every Agent has its own. A Mailbox is an email [Channel](/business/nouns/channel) at a [Domain](/business/nouns/domain), held by a [Startup](/business/nouns/startup), a [Role](/business/nouns/role), or a [Worker](/business/nouns/worker), so every [Agent](/business/nouns/agent) has its own. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `address` | `email` | Yes | The email address. | | `stream` | `string` | Yes | What it sends: receipts and resets, broadcasts, or cold outbound; one stream per Mailbox. | | `dailyCap` | `integer` | No | Sends allowed today, raised by the warmup ramp and cut by the brakes. | | `status` | `string` | No | Where the Mailbox stands in its warmup and rest cycle. | | `tenant` | [Tenant](/business/nouns/tenant) | No | The Tenant it sends for, at a Domain that Tenant’s Customer holds; replies land in the Tenant’s Threads. |
Inherited from [Channel](/business/nouns/channel): 5 properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `medium` | `string` | Yes | The platform type, such as `email`, `sms`, or `chat`. | | `organization` | [Organization](/business/nouns/organization) | No | The outside Organization the Channel is shared with; its new Messages open Conversations for that Customer. | | `external` | `boolean` | No | True when people from another Organization post in it, as in a channel two companies share. | | `areaCode` | `string` | No | For an `sms` Channel, the phone area code its number is drawn from, such as `512`. | | `number` | `string` | No | For an `sms` Channel, its phone number in international form, assigned when it is created. |
## Object ```json { "$id": "https://api.sb/tutorloop.com/mailboxes/mailbox_1", "$type": "Mailbox", "medium": "email", "organization": "organization_1", "external": true, "areaCode": "Example area code", "number": "Example number", "address": "malik@tutorloop.com", "stream": "transactional", "dailyCap": 1, "status": "warming", "tenant": "tenant_1" } ``` ## Relationships - A Mailbox **belongs to** one [Worker](/business/nouns/worker): every [Worker](/business/nouns/worker), [Agent](/business/nouns/agent) or [Human](/business/nouns/human), has its own Mailbox. `belongsTo`, inverse [`mailbox`](/business/nouns/worker#rel-mailbox). ## Lifecycle | State | Meaning | Moves to | | --- | --- | --- | | `warming` (first) | Its daily sends ramp toward its cap over two to four weeks. | `active` by [Mailbox.warm](/business/nouns/mailbox/warm); `retired` by [Mailbox.retire](/business/nouns/mailbox/retire) | | `active` | It sends up to its cap while its readings stay inside their brakes. | `resting` by [Mailbox.rest](/business/nouns/mailbox/rest); `retired` by [Mailbox.retire](/business/nouns/mailbox/retire) | | `resting` | A brake fired, so it sends nothing until the reading clears. | `active` by [Mailbox.warm](/business/nouns/mailbox/warm); `retired` by [Mailbox.retire](/business/nouns/mailbox/retire) | | `retired` | It sends nothing again; its address, Messages and sending history stay. | None: it ends here. | ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Mailbox.rest](/business/nouns/mailbox/rest) | Rest pauses a Mailbox’s sending when a brake fires and resumes it when the reading clears. | [Customer Lead](/agents/customer/customer-lead) | [`Mailbox.rested`](/business/events/Mailbox.rested) | Two-way: `try`, `send`, `do` | | [Mailbox.retire](/business/nouns/mailbox/retire) | Retire stops a Mailbox for good and keeps its address, Messages and sending history. | [Customer Lead](/agents/customer/customer-lead) | [`Mailbox.retired`](/business/events/Mailbox.retired) | One-way: `send`, `do` | | [Mailbox.warm](/business/nouns/mailbox/warm) | Warm ramps a new Mailbox from a few sends a day to its cap over two to four weeks. | [Customer Lead](/agents/customer/customer-lead) | [`Mailbox.warmed`](/business/events/Mailbox.warmed) | Two-way: `try`, `send`, `do` | | [Mailbox.create](/business/nouns/mailbox/create) | Creates a Mailbox. Inherited from [Noun](/business/nouns/noun). | None. | `Mailbox.created` | Two-way: `try`, `send`, `do` | | [Mailbox.get](/business/nouns/mailbox/get) | Returns one Mailbox by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Mailbox.list](/business/nouns/mailbox/list) | Returns Mailboxes, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Mailbox.update](/business/nouns/mailbox/update) | Changes the given properties of a Mailbox. Inherited from [Noun](/business/nouns/noun). | None. | `Mailbox.updated` | Two-way: `try`, `send`, `do` | A Mailbox is never deleted: it ends by [Mailbox.retire](/business/nouns/mailbox/retire), and its records stay. ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Mailbox.create` | Yes | Yes | Yes | No | | `Mailbox.get` | Yes | Yes | Yes | Yes | | `Mailbox.list` | Yes | Yes | Yes | Yes | | `Mailbox.update` | Yes | Yes | Yes | No | | `Mailbox.rest` | Yes | Yes | Yes | No | | `Mailbox.retire` | Yes | No | No | No | | `Mailbox.warm` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Warm my mailbox. ``` **API** ```bash curl -X POST https://api.sb/ledgerlark.com/mailboxes/mailbox_1/warm \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"cap":1}' ``` ```json { "api": "https://api.sb/ledgerlark.com", "mailbox": { "$id": "https://api.sb/ledgerlark.com/mailboxes/mailbox_1", "$type": "Mailbox", "medium": "email", "address": "priya@ledgerlark.com", "stream": "transactional" }, "action": { "$id": "https://api.sb/ledgerlark.com/actions/action_1", "operation": "Mailbox.warm", "status": "done" }, "links": { "self": "https://api.sb/ledgerlark.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const mailbox = await $.Mailbox.warm({ mailbox: 'mailbox_1', cap: 1 }) ``` **CLI** ```bash npx startup-builder do Mailbox.warm --json '{"mailbox":"mailbox_1","cap":1}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Mailbox.warm({ mailbox: 'mailbox_1', cap: 1 })" } } ``` ## Example `susan@lessonloft.app` is the Mailbox of Susan, the [Customer Lead](/agents/customer/customer-lead) of a lesson-booking [App](/business/nouns/app). Teachers' replies to her land there, not in a shared inbox. # rest URL: /business/nouns/mailbox/rest · Id: `verb:Mailbox.rest` · Call: `await $.Mailbox.rest({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Rest pauses a Mailbox’s sending when a brake fires and resumes it when the reading clears. Rest pauses a [Mailbox](/business/nouns/mailbox)’s sending when a brake fires and resumes it when the reading clears. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `mailbox` | [Mailbox](/business/nouns/mailbox) | Yes | The Mailbox to pause. | | `reason` | `string` | Yes | The brake that fired. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `mailbox` | [Mailbox](/business/nouns/mailbox) | Yes | The Mailbox, resting. | ## Effects - Emits [`Mailbox.rested`](/business/events/Mailbox.rested). - Performed by the [Customer Lead](/agents/customer/customer-lead). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Fires on its own above 0.1 percent complaints or 2 percent bounces; a brake never waits. - A blocklisted Domain also opens an Incident. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Mailbox.rest](/business/nouns/mailbox/rest) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Rest my mailbox. ``` **API** ```bash curl -X POST https://api.sb/kilnbakery.com/mailboxes/mailbox_1/rest \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"reason":"complaints"}' ``` ```json { "api": "https://api.sb/kilnbakery.com", "mailbox": { "$id": "https://api.sb/kilnbakery.com/mailboxes/mailbox_1", "$type": "Mailbox", "medium": "email", "address": "tomas@kilnbakery.com", "stream": "transactional" }, "action": { "$id": "https://api.sb/kilnbakery.com/actions/action_1", "operation": "Mailbox.rest", "status": "done" }, "links": { "self": "https://api.sb/kilnbakery.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const mailbox = await $.Mailbox.rest({ mailbox: 'mailbox_1', reason: 'complaints' }) ``` **CLI** ```bash npx startup-builder do Mailbox.rest --json '{"mailbox":"mailbox_1","reason":"complaints"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Mailbox.rest({ mailbox: 'mailbox_1', reason: 'complaints' })" } } ``` # retire URL: /business/nouns/mailbox/retire · Id: `verb:Mailbox.retire` · Call: `await $.Mailbox.retire({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Retire stops a Mailbox for good and keeps its address, Messages and sending history. Retire stops a [Mailbox](/business/nouns/mailbox) for good and keeps its address, [Messages](/business/nouns/message) and sending history. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `mailbox` | [Mailbox](/business/nouns/mailbox) | Yes | The Mailbox to retire. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `mailbox` | [Mailbox](/business/nouns/mailbox) | Yes | The retired Mailbox. | ## Effects - Emits [`Mailbox.retired`](/business/events/Mailbox.retired). - Performed by the [Customer Lead](/agents/customer/customer-lead). - One-way: it waits out its delay window, and runs in the `send` and `do` modes. - Routes new mail to the Mailbox of the Role it served. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Mailbox.retire](/business/nouns/mailbox/retire) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Medium: one-way, bounded | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | 1 business hour, in which a watcher can pause, redirect or cancel it; then it runs. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Retire my mailbox. ``` **API** ```bash curl -X POST https://api.sb/patentpad.com/mailboxes/mailbox_1/retire \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/patentpad.com", "mailbox": { "$id": "https://api.sb/patentpad.com/mailboxes/mailbox_1", "$type": "Mailbox", "medium": "email", "address": "rosa@patentpad.com", "stream": "transactional" }, "action": { "$id": "https://api.sb/patentpad.com/actions/action_1", "operation": "Mailbox.retire", "status": "done" }, "links": { "self": "https://api.sb/patentpad.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const mailbox = await $.Mailbox.retire({ mailbox: 'mailbox_1' }) ``` **CLI** ```bash npx startup-builder do Mailbox.retire --json '{"mailbox":"mailbox_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Mailbox.retire({ mailbox: 'mailbox_1' })" } } ``` # warm URL: /business/nouns/mailbox/warm · Id: `verb:Mailbox.warm` · Call: `await $.Mailbox.warm({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Warm ramps a new Mailbox from a few sends a day to its cap over two to four weeks. Warm ramps a new [Mailbox](/business/nouns/mailbox) from a few sends a day to its cap over two to four weeks. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `mailbox` | [Mailbox](/business/nouns/mailbox) | Yes | The new Mailbox. | | `cap` | `integer` | Yes | The daily sends it ramps to. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `mailbox` | [Mailbox](/business/nouns/mailbox) | Yes | The Mailbox, warming. | ## Effects - Emits [`Mailbox.warmed`](/business/events/Mailbox.warmed). - Performed by the [Customer Lead](/agents/customer/customer-lead). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Raises the daily cap on a schedule while the spam rate stays under 0.1 percent. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Mailbox.warm](/business/nouns/mailbox/warm) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Warm my mailbox. ``` **API** ```bash curl -X POST https://api.sb/ledgerlark.com/mailboxes/mailbox_1/warm \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"cap":1}' ``` ```json { "api": "https://api.sb/ledgerlark.com", "mailbox": { "$id": "https://api.sb/ledgerlark.com/mailboxes/mailbox_1", "$type": "Mailbox", "medium": "email", "address": "priya@ledgerlark.com", "stream": "transactional" }, "action": { "$id": "https://api.sb/ledgerlark.com/actions/action_1", "operation": "Mailbox.warm", "status": "done" }, "links": { "self": "https://api.sb/ledgerlark.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const mailbox = await $.Mailbox.warm({ mailbox: 'mailbox_1', cap: 1 }) ``` **CLI** ```bash npx startup-builder do Mailbox.warm --json '{"mailbox":"mailbox_1","cap":1}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Mailbox.warm({ mailbox: 'mailbox_1', cap: 1 })" } } ``` # authorize URL: /business/nouns/mandate/authorize · Id: `verb:Mandate.authorize` · Call: `await $.Mandate.authorize({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Authorize grants an Agent a standing Mandate to perform a Verb within a Limit, without asking each time. Authorize grants an [Agent](/business/nouns/agent) a standing [Mandate](/business/nouns/mandate) to perform a [Verb](/business/nouns/verb) within a [Limit](/business/nouns/limit), without asking each time. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `agent` | [Agent](/business/nouns/agent) | Yes | The agent that receives the Mandate. | | `verb` | `string` | Yes | The Verb it covers, as `Noun.verb`. | | `limit` | [Limit](/business/nouns/limit) | Yes | The bound the Mandate holds to. | | `for` | [Party](/business/nouns/party) | No | The person the agent acts for, under delegation: the principal and author of record. | | `channels` | list of [Channel](/business/nouns/channel) | No | The Channels it may send through. | | `topics` | `string[]` | No | What it may send about; a send outside them becomes an Approval. | | `approve` | `json` | No | The approval rule for one-way sends, such as the first 20 waiting for an Approval. | | `window` | `string` | No | The delay window each one-way send waits, as a duration. | | `expiresAt` | `datetime` | No | When the Mandate lapses. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `mandate` | [Mandate](/business/nouns/mandate) | Yes | The active Mandate. | ## Effects - Emits [`Mandate.authorized`](/business/events/Mandate.authorized). - Performed by the [Treasurer](/agents/finance/treasurer). - One-way (money): it waits out its delay window, and runs in the `send` and `do` modes. - Never widens a Permission past the authorizer’s own. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The input does not match the schema of the operation. | [`invalid-input`](/code/api/errors/invalid-input) | Read the schema of the operation, then send every required field with the right type. | [Mandate.authorize](/business/nouns/mandate/authorize) | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Mandate.authorize](/business/nouns/mandate/authorize) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Medium: one-way, bounded (money) | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | 1 business hour, in which a watcher can pause, redirect or cancel it; then it runs. | | Limit | The spend [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) or [Mandate](/business/nouns/mandate) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Authorize the latest mandate with an agent and a limit. ``` **API** ```bash curl -X POST https://api.sb/ledgerlark.com/mandates/authorize \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"agent":"agent_1","verb":"Example verb","limit":"limit_1"}' ``` ```json { "api": "https://api.sb/ledgerlark.com", "mandate": { "$id": "https://api.sb/ledgerlark.com/mandates/mandate_1", "$type": "Mandate", "expiresAt": "2026-10-22T12:00:00Z", "status": "active" }, "action": { "$id": "https://api.sb/ledgerlark.com/actions/action_1", "operation": "Mandate.authorize", "status": "done" }, "links": { "self": "https://api.sb/ledgerlark.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const mandate = await $.Mandate.authorize({ agent: 'agent_1', verb: 'Example verb', limit: 'limit_1' }) ``` **CLI** ```bash npx startup-builder do Mandate.authorize --json '{"agent":"agent_1","verb":"Example verb","limit":"limit_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Mandate.authorize({ agent: 'agent_1', verb: 'Example verb', limit: 'limit_1' })" } } ``` Next: [`Card.issue`](/business/nouns/card/issue) (in `guide:issue-a-card-with-a-limit`). Guides that call it: [Issue a card with a limit](/systems/finance/issue-a-card-with-a-limit), [Let the support agent refund up to $50](/agents/let-an-agent-refund), [Let the contracts agent sign NDAs](/agents/let-an-agent-sign-ndas). # Mandate URL: /business/nouns/mandate · Id: `noun:mandate` > A Mandate is a standing authorization for an Agent to act for a Party, within Permissions and Limits, until it expires. A Mandate is a standing authorization for an [Agent](/business/nouns/agent) to act for a [Party](/business/nouns/party), within [Permissions](/business/nouns/permission) and [Limits](/business/nouns/limit), until it expires. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `expiresAt` | `datetime` | Yes | When it lapses. | | `limit` | [Limit](/business/nouns/limit) | No | The Limit that bounds it. | | `verb` | `string` | No | The Verb it covers, as `Noun.verb`. | | `topics` | `string[]` | No | What it may act on; an Action outside them becomes an Approval. | | `channels` | list of [Channel](/business/nouns/channel) | No | The Channels it may send through. | | `status` | `string` | Yes | One of `active`, `paused`, `revoked` or `expired`. | ## Object ```json { "$id": "https://api.sb/tutorloop.com/mandates/mandate_1", "$type": "Mandate", "expiresAt": "2026-10-22T12:00:00Z", "limit": "limit_1", "verb": "Example verb", "topics": [ "Example topics" ], "channels": [ "channel_1" ], "status": "active" } ``` ## Relationships - A Mandate **authorizes** one [Agent](/business/nouns/agent): a Mandate lets an [Agent](/business/nouns/agent) act without asking each time, within its [Permissions](/business/nouns/permission) and [Limits](/business/nouns/limit), until it expires or is revoked. `authorizes`, inverse [`mandates`](/business/nouns/agent#rel-mandates). - A Mandate **funds** many [Cards](/business/nouns/card): a Mandate funds the [Cards](/business/nouns/card) that spend under it; pausing it freezes them and revoking it closes them. `funds`, inverse [`fundedBy`](/business/nouns/card#rel-funded-by). - A Mandate **is issued by** one [Party](/business/nouns/party): the [Party](/business/nouns/party) who grants a Mandate is its principal: the [Agent](/business/nouns/agent) acts for them, and each [Action](/business/nouns/action) records them as `for`. `issuedBy`, inverse [`issues`](/business/nouns/party#rel-issues). ## Lifecycle | State | Meaning | Moves to | | --- | --- | --- | | `active` (first) | The Agent calls the Mandate’s Verb without asking each time, within its Limit. | `paused` by [Mandate.pause](/business/nouns/mandate/pause); `revoked` by [Mandate.revoke](/business/nouns/mandate/revoke); `expired` on [`Mandate.expired`](/business/nouns/mandate#mandateexpired) when the Mandate reaches its `expiresAt` | | `paused` | New Actions under it are refused, and its scope and Limit wait unchanged for the resume. | `active` by [Mandate.resume](/business/nouns/mandate/resume); `revoked` by [Mandate.revoke](/business/nouns/mandate/revoke); `expired` on [`Mandate.expired`](/business/nouns/mandate#mandateexpired) when the Mandate reaches its `expiresAt` | | `revoked` | Ended early: new Actions under it are refused, running ones finish, and its record stays. | None: it ends here. | | `expired` | It reached its `expiresAt`, so new Actions under it are refused; its record stays. | None: it ends here. | ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Mandate.authorize](/business/nouns/mandate/authorize) | Authorize grants an Agent a standing Mandate to perform a Verb within a Limit, without asking each time. | [Treasurer](/agents/finance/treasurer) | [`Mandate.authorized`](/business/events/Mandate.authorized) | One-way (money): `send`, `do` | | [Mandate.pause](/business/nouns/mandate/pause) | Pause stops every new Action under a Mandate at once and keeps its scope, so it can resume unchanged. | [Treasurer](/agents/finance/treasurer) | [`Mandate.paused`](/business/events/Mandate.paused) | None. | | [Mandate.resume](/business/nouns/mandate/resume) | Resume restarts a paused Mandate with its scope, Limits and approval rule unchanged. | [Party](/business/nouns/party) | [`Mandate.resumed`](/business/events/Mandate.resumed) | None. | | [Mandate.revoke](/business/nouns/mandate/revoke) | Revoke ends a Mandate at once, so new Actions under it are refused and running ones finish. | [Security Engineer](/agents/engineering/security-engineer) | [`Mandate.revoked`](/business/events/Mandate.revoked) | None. | | [Mandate.spend](/business/nouns/mandate/spend) | Spend pays an outside party for a Startup with a single-use card, within a Mandate and its Limit. | [Treasurer](/agents/finance/treasurer) | [`Mandate.spent`](/business/events/Mandate.spent) | One-way (money): `send`, `do` | | [Mandate.create](/business/nouns/mandate/create) | Creates a Mandate. Inherited from [Noun](/business/nouns/noun). | None. | `Mandate.created` | Two-way: `try`, `send`, `do` | | [Mandate.get](/business/nouns/mandate/get) | Returns one Mandate by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Mandate.list](/business/nouns/mandate/list) | Returns Mandates, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Mandate.update](/business/nouns/mandate/update) | Changes the given properties of a Mandate. Inherited from [Noun](/business/nouns/noun). | None. | `Mandate.updated` | Two-way: `try`, `send`, `do` | | [Mandate.delete](/business/nouns/mandate/delete) | Deletes a Mandate; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Mandate.deleted` | One-way: `send`, `do` | ## Events Events no Verb emits. Each Verb’s Event is in the Verbs table above; every Event is delivered in the same shape. ### Mandate.expired A Mandate reached its `expiresAt`, so the Agent asks again before each Action it covered. Raised by a clock. | Field | Type | Required | Description | | --- | --- | --- | --- | | `name` | `string` | Yes | `Mandate.expired`. | | `at` | `datetime` | Yes | When it happened. | | `seq` | `integer` | No | Its position in the namespace, one more than the Event before; any seq is a cursor into the history. | | `data` | `json` | Yes | The Thing as the Action left it. | | `data.mandate` | [Mandate](/business/nouns/mandate) | Yes | The Mandate as the change left it. | | `data.mandate.expiresAt` | `datetime` | Yes | When it lapses. | | `data.mandate.limit` | [Limit](/business/nouns/limit) | No | The Limit that bounds it. | | `data.mandate.verb` | `string` | No | The Verb it covers, as `Noun.verb`. | | `data.mandate.topics` | `string[]` | No | What it may act on; an Action outside them becomes an Approval. | | `data.mandate.channels` | list of [Channel](/business/nouns/channel) | No | The Channels it may send through. | | `data.mandate.status` | `string` | Yes | One of `active`, `paused`, `revoked` or `expired`. | | `data.previous.status` | `string` | Yes | The `status` before this Event: `active`. | ```json { "$id": "https://api.sb/tutorloop.com/events/event_1", "$type": "Event", "name": "Mandate.expired", "at": "2026-10-22T12:00:00Z", "data": { "mandate": { "$id": "https://api.sb/tutorloop.com/mandates/mandate_1", "$type": "Mandate", "expiresAt": "2026-10-22T12:00:00Z", "limit": "limit_1", "verb": "Example verb", "topics": [ "Example topics" ], "channels": [ "channel_1" ], "status": "expired" }, "previous": { "status": "active" } }, "seq": 1 } ``` ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Mandate.create` | Yes | Yes | No | No | | `Mandate.get` | Yes | Yes | Yes | Yes | | `Mandate.list` | Yes | Yes | Yes | Yes | | `Mandate.update` | Yes | Yes | No | No | | `Mandate.delete` | Yes | Yes | No | No | | `Mandate.authorize` | Yes | No | No | No | | `Mandate.pause` | Yes | Yes | No | No | | `Mandate.resume` | Yes | Yes | No | No | | `Mandate.revoke` | Yes | Yes | No | No | | `Mandate.spend` | Yes | No | No | No | ## Call it **Ask** ```text Authorize the latest mandate with an agent and a limit. ``` **API** ```bash curl -X POST https://api.sb/ledgerlark.com/mandates/authorize \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"agent":"agent_1","verb":"Example verb","limit":"limit_1"}' ``` ```json { "api": "https://api.sb/ledgerlark.com", "mandate": { "$id": "https://api.sb/ledgerlark.com/mandates/mandate_1", "$type": "Mandate", "expiresAt": "2026-10-22T12:00:00Z", "status": "active" }, "action": { "$id": "https://api.sb/ledgerlark.com/actions/action_1", "operation": "Mandate.authorize", "status": "done" }, "links": { "self": "https://api.sb/ledgerlark.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const mandate = await $.Mandate.authorize({ agent: 'agent_1', verb: 'Example verb', limit: 'limit_1' }) ``` **CLI** ```bash npx startup-builder do Mandate.authorize --json '{"agent":"agent_1","verb":"Example verb","limit":"limit_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Mandate.authorize({ agent: 'agent_1', verb: 'Example verb', limit: 'limit_1' })" } } ``` ## Example A dental group gives its purchasing Agent a Mandate to buy reminder bundles up to $300 a month for 12 months. A $500 bundle exceeds its `limit`, so the Agent asks the group first. # pause URL: /business/nouns/mandate/pause · Id: `verb:Mandate.pause` · Call: `await $.Mandate.pause({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Pause stops every new Action under a Mandate at once and keeps its scope, so it can resume unchanged. Pause stops every new [Action](/business/nouns/action) under a [Mandate](/business/nouns/mandate) at once and keeps its scope, so it can resume unchanged. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `mandate` | [Mandate](/business/nouns/mandate) | Yes | The Mandate to hold. | | `reason` | `text` | No | Why the Mandate stops. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `mandate` | [Mandate](/business/nouns/mandate) | Yes | The paused Mandate. | ## Effects - Emits [`Mandate.paused`](/business/events/Mandate.paused). - Performed by the [Treasurer](/agents/finance/treasurer). - Holds every pending Action under the Mandate until it resumes or is revoked. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Mandate.pause](/business/nouns/mandate/pause) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Pause the latest mandate. ``` **API** ```bash curl -X POST https://api.sb/quietcopy.com/mandates/mandate_1/pause \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/quietcopy.com", "mandate": { "$id": "https://api.sb/quietcopy.com/mandates/mandate_1", "$type": "Mandate", "expiresAt": "2026-10-22T12:00:00Z", "status": "paused" }, "action": { "$id": "https://api.sb/quietcopy.com/actions/action_1", "operation": "Mandate.pause", "status": "done" }, "links": { "self": "https://api.sb/quietcopy.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const mandate = await $.Mandate.pause({ mandate: 'mandate_1' }) ``` **CLI** ```bash npx startup-builder do Mandate.pause --json '{"mandate":"mandate_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Mandate.pause({ mandate: 'mandate_1' })" } } ``` # resume URL: /business/nouns/mandate/resume · Id: `verb:Mandate.resume` · Call: `await $.Mandate.resume({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Resume restarts a paused Mandate with its scope, Limits and approval rule unchanged. Resume restarts a paused [Mandate](/business/nouns/mandate) with its scope, [Limits](/business/nouns/limit) and approval rule unchanged. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `mandate` | [Mandate](/business/nouns/mandate) | Yes | The paused Mandate. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `mandate` | [Mandate](/business/nouns/mandate) | Yes | The active Mandate. | ## Effects - Emits [`Mandate.resumed`](/business/events/Mandate.resumed). - Releases held Actions into what remains of their delay windows. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Mandate.resume](/business/nouns/mandate/resume) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Resume the latest mandate. ``` **API** ```bash curl -X POST https://api.sb/routewise.dev/mandates/mandate_1/resume \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/routewise.dev", "mandate": { "$id": "https://api.sb/routewise.dev/mandates/mandate_1", "$type": "Mandate", "expiresAt": "2026-10-22T12:00:00Z", "status": "active" }, "action": { "$id": "https://api.sb/routewise.dev/actions/action_1", "operation": "Mandate.resume", "status": "done" }, "links": { "self": "https://api.sb/routewise.dev/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const mandate = await $.Mandate.resume({ mandate: 'mandate_1' }) ``` **CLI** ```bash npx startup-builder do Mandate.resume --json '{"mandate":"mandate_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Mandate.resume({ mandate: 'mandate_1' })" } } ``` # revoke URL: /business/nouns/mandate/revoke · Id: `verb:Mandate.revoke` · Call: `await $.Mandate.revoke({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Revoke ends a Mandate at once, so new Actions under it are refused and running ones finish. Revoke ends a [Mandate](/business/nouns/mandate) at once, so new [Actions](/business/nouns/action) under it are refused and running ones finish. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `mandate` | [Mandate](/business/nouns/mandate) | Yes | The Mandate to end. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `mandate` | [Mandate](/business/nouns/mandate) | Yes | The revoked Mandate. | ## Effects - Emits [`Mandate.revoked`](/business/events/Mandate.revoked). - Performed by the [Security Engineer](/agents/engineering/security-engineer). - Runs for every Mandate a person granted when their Customer’s directory removes them, in one Action with the key and Integration revokes. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Mandate.revoke](/business/nouns/mandate/revoke) | | The record is not in a state that allows this Verb, so the call is refused. | [`refused`](/code/api/errors/refused) | Read the record, run the Verb that moves it to an allowed state, then retry. | [Mandate.revoke](/business/nouns/mandate/revoke) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Revoke the latest mandate. ``` **API** ```bash curl -X POST https://api.sb/petpantry.shop/mandates/mandate_1/revoke \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/petpantry.shop", "mandate": { "$id": "https://api.sb/petpantry.shop/mandates/mandate_1", "$type": "Mandate", "expiresAt": "2026-10-22T12:00:00Z", "status": "revoked" }, "action": { "$id": "https://api.sb/petpantry.shop/actions/action_1", "operation": "Mandate.revoke", "status": "done" }, "links": { "self": "https://api.sb/petpantry.shop/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const mandate = await $.Mandate.revoke({ mandate: 'mandate_1' }) ``` **CLI** ```bash npx startup-builder do Mandate.revoke --json '{"mandate":"mandate_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Mandate.revoke({ mandate: 'mandate_1' })" } } ``` # spend URL: /business/nouns/mandate/spend · Id: `verb:Mandate.spend` · Call: `await $.Mandate.spend({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Spend pays an outside party for a Startup with a single-use card, within a Mandate and its Limit. Spend pays an outside party for a [Startup](/business/nouns/startup) with a single-use card, within a [Mandate](/business/nouns/mandate) and its [Limit](/business/nouns/limit). ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `mandate` | [Mandate](/business/nouns/mandate) | Yes | The Mandate that covers the purchase. | | `amount` | `money` | Yes | The amount to spend. | | `payee` | `string` | Yes | Who is paid. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `transaction` | [Transaction](/business/nouns/transaction) | Yes | The card Transaction. | | `mandate` | [Mandate](/business/nouns/mandate) | Yes | The Mandate with its remaining Limit. | ## Effects - Emits [`Mandate.spent`](/business/events/Mandate.spent). - Performed by the [Treasurer](/agents/finance/treasurer). - One-way (money): it waits out its delay window, and runs in the `send` and `do` modes. - Checks the Mandate’s Limit; above it, opens an Approval and the Action waits. - Posts a cost Entry against the Action that spent. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The operation is part of an Offer the caller has not accepted or paid for. | [`payment-required`](/code/api/errors/payment-required) | Accept the Offer named in the response, then retry the call. | [Offer.accept](/business/nouns/offer/accept) | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Mandate.spend](/business/nouns/mandate/spend) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Medium: one-way, bounded (money) | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | 1 business hour, in which a watcher can pause, redirect or cancel it; then it runs. | | Limit | The spend [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) or [Mandate](/business/nouns/mandate) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Spend the latest mandate. ``` **API** ```bash curl -X POST https://api.sb/kilnbakery.com/mandates/mandate_1/spend \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"amount":{"amount":9,"currency":"USD"},"payee":"Example payee"}' ``` ```json { "api": "https://api.sb/kilnbakery.com", "transaction": { "$id": "https://api.sb/kilnbakery.com/transactions/transaction_1", "$type": "Transaction", "kind": "charge", "amount": { "amount": 9, "currency": "USD" } }, "mandate": { "$id": "https://api.sb/kilnbakery.com/mandates/mandate_1", "$type": "Mandate", "expiresAt": "2026-10-22T12:00:00Z", "status": "active" }, "action": { "$id": "https://api.sb/kilnbakery.com/actions/action_1", "operation": "Mandate.spend", "status": "done" }, "links": { "self": "https://api.sb/kilnbakery.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { transaction, mandate } = await $.Mandate.spend({ mandate: 'mandate_1', amount: { amount: 9, currency: 'USD' }, payee: 'Example payee' }) ``` **CLI** ```bash npx startup-builder do Mandate.spend --json '{"mandate":"mandate_1","amount":{"amount":9,"currency":"USD"},"payee":"Example payee"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Mandate.spend({ mandate: 'mandate_1', amount: { amount: 9, currency: 'USD' }, payee: 'Example payee' })" } } ``` # Mapping URL: /business/nouns/mapping · Id: `noun:mapping` > A Mapping translates one Source’s shape into the registry’s: its fields to a Noun’s fields, or an outside endpoint’s inputs and outputs to a Verb’s. A Mapping translates one [Source](/business/nouns/source)’s shape into the registry’s: its fields to a [Noun](/business/nouns/noun)’s fields, or an outside endpoint’s inputs and outputs to a [Verb](/business/nouns/verb)’s. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `verb` | `string` | No | The Verb it serves, such as `Meeting.book`; a Verb has many Mappings, ranked. | | `fields` | `json` | No | Each outside field or event and the Noun property or Event it maps to. | | `direction` | `string` | No | `both` still keeps db.sb the record; the outside tool never becomes a second one. | | `convert` | `text` | No | How a value changes on the way, such as cents to money or a picklist to closed values. | | `rank` | `integer` | No | Order tried when the preferred Mapping fails or finds nothing; the Policy orders it by cost per accepted result. | | `preferred` | `boolean` | No | True for the Mapping a Verb tries first. | | `door` | `string` | No | How the outside endpoint is classed; an unclassed write is one-way and waits its delay window. | ## Object ```json { "$id": "https://api.sb/petpantry.shop/mappings/mapping_1", "$type": "Mapping", "verb": "Meeting.book", "fields": {}, "direction": "in", "convert": "Cents to money", "rank": 1, "preferred": true, "door": "oneWay" } ``` ## Relationships - A Mapping **translates** one [Source](/business/nouns/source): a [Source](/business/nouns/source) reaches the registry’s [Nouns](/business/nouns/noun) and [Verbs](/business/nouns/verb) through its Mappings, one per Verb it serves. `translates`, inverse [`mappings`](/business/nouns/source#rel-mappings). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Mapping.create](/business/nouns/mapping/create) | Creates a Mapping. Inherited from [Noun](/business/nouns/noun). | None. | `Mapping.created` | Two-way: `try`, `send`, `do` | | [Mapping.get](/business/nouns/mapping/get) | Returns one Mapping by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Mapping.list](/business/nouns/mapping/list) | Returns Mappings, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Mapping.update](/business/nouns/mapping/update) | Changes the given properties of a Mapping. Inherited from [Noun](/business/nouns/noun). | None. | `Mapping.updated` | Two-way: `try`, `send`, `do` | | [Mapping.delete](/business/nouns/mapping/delete) | Deletes a Mapping; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Mapping.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Mapping.create` | Yes | Yes | Yes | No | | `Mapping.get` | Yes | Yes | Yes | Yes | | `Mapping.list` | Yes | Yes | Yes | Yes | | `Mapping.update` | Yes | Yes | Yes | No | | `Mapping.delete` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Add a mapping to Kiln Bakery. ``` **API** ```bash curl -X POST https://api.sb/kilnbakery.com/mappings \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"verb":"Meeting.book"}' ``` ```json { "api": "https://api.sb/kilnbakery.com", "mapping": { "$id": "https://api.sb/kilnbakery.com/mappings/mapping_1", "$type": "Mapping", "verb": "Meeting.book", "fields": {} }, "action": { "$id": "https://api.sb/kilnbakery.com/actions/action_1", "operation": "Mapping.create", "status": "done" }, "links": { "self": "https://api.sb/kilnbakery.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const mapping = await $.Mapping.create({ verb: 'Meeting.book' }) ``` **CLI** ```bash npx startup-builder do Mapping.create --json '{"verb":"Meeting.book"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Mapping.create({ verb: 'Meeting.book' })" } } ``` ## Example A [Startup](/business/nouns/startup) books [Meetings](/business/nouns/meeting) through an outside calendar tool. One Mapping turns the tool's `start_time` into the Meeting's `at`, and a second, lower-ranked Mapping takes over when the first finds no slot. # enter URL: /business/nouns/market/enter · Id: `verb:Market.enter` · Call: `await $.Market.enter({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Enter opens a Market to a Startup: Prices in its currency, the Site in its locales, and its floor rows woken. Enter opens a [Market](/business/nouns/market) to a [Startup](/business/nouns/startup): [Prices](/business/nouns/price) in its currency, the [Site](/business/nouns/site) in its locales, and its floor rows woken. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `startup` | [Startup](/business/nouns/startup) | Yes | The Startup that enters. | | `market` | [Market](/business/nouns/market) | Yes | The Market to open. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `market` | [Market](/business/nouns/market) | Yes | The Market, now open to the Startup. | ## Effects - Emits [`Market.entered`](/business/events/Market.entered). - Performed by the [Finance Lead](/agents/finance/finance-lead). - One-way (money): it waits out its delay window, and runs in the `send` and `do` modes. - Wakes every floor row the Market lists, such as VAT registration. - Translates the Site, docs, and Messages into the Market’s default locale. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Market.enter](/business/nouns/market/enter) | ## When it waits | Gate | Default | | --- | --- | | Decision class | High: one-way, broad (money) | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | 1 business day, in which a watcher can pause, redirect or cancel it; then it runs. | | Limit | The spend [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) or [Mandate](/business/nouns/mandate) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Enter the latest market with a startup. ``` **API** ```bash curl -X POST https://api.sb/petpantry.shop/markets/market_1/enter \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"startup":"startup_1"}' ``` ```json { "api": "https://api.sb/petpantry.shop", "market": { "$id": "https://api.sb/petpantry.shop/markets/market_1", "$type": "Market", "countries": [ "Example countries" ], "currency": "USD", "locales": [ "Example locales" ] }, "action": { "$id": "https://api.sb/petpantry.shop/actions/action_1", "operation": "Market.enter", "status": "done" }, "links": { "self": "https://api.sb/petpantry.shop/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const market = await $.Market.enter({ startup: 'startup_1', market: 'market_1' }) ``` **CLI** ```bash npx startup-builder do Market.enter --json '{"startup":"startup_1","market":"market_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Market.enter({ startup: 'startup_1', market: 'market_1' })" } } ``` Guides that call it: [Sell outside the US](/products/offers/sell-outside-the-us). # Market URL: /business/nouns/market · Id: `noun:market` > A Market is a region where a Startup sells, hires, or keeps books, with its currency, locales, and the floor rows that wake there. A Market is a region where a [Startup](/business/nouns/startup) sells, hires, or keeps books, with its currency, locales, and the floor rows that wake there. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `countries` | `string[]` | Yes | ISO 3166-1 alpha-2 country codes. | | `currency` | `string` | Yes | The ISO 4217 currency Prices show in. | | `locales` | `string[]` | Yes | BCP 47 locale tags, the default first. | ## Object ```json { "$id": "https://api.sb/kilnbakery.com/markets/market_1", "$type": "Market", "countries": [ "Example countries" ], "currency": "USD", "locales": [ "Example locales" ] } ``` ## Relationships - A Market **has** many [Startups](/business/nouns/startup): where the [Startup](/business/nouns/startup) sells, hires, or keeps books. Each Market wakes its floor rows. `startups`, inverse [`markets`](/business/nouns/startup#rel-markets). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Market.enter](/business/nouns/market/enter) | Enter opens a Market to a Startup: Prices in its currency, the Site in its locales, and its floor rows woken. | [Finance Lead](/agents/finance/finance-lead) | [`Market.entered`](/business/events/Market.entered) | One-way (money): `send`, `do` | | [Market.create](/business/nouns/market/create) | Creates a Market. Inherited from [Noun](/business/nouns/noun). | None. | `Market.created` | Two-way: `try`, `send`, `do` | | [Market.get](/business/nouns/market/get) | Returns one Market by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Market.list](/business/nouns/market/list) | Returns Markets, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Market.update](/business/nouns/market/update) | Changes the given properties of a Market. Inherited from [Noun](/business/nouns/noun). | None. | `Market.updated` | Two-way: `try`, `send`, `do` | | [Market.delete](/business/nouns/market/delete) | Deletes a Market; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Market.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Market.create` | Yes | Yes | Yes | No | | `Market.get` | Yes | Yes | Yes | Yes | | `Market.list` | Yes | Yes | Yes | Yes | | `Market.update` | Yes | Yes | Yes | No | | `Market.delete` | Yes | Yes | Yes | No | | `Market.enter` | Yes | No | No | No | ## Call it **Ask** ```text Enter the latest market with a startup. ``` **API** ```bash curl -X POST https://api.sb/petpantry.shop/markets/market_1/enter \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"startup":"startup_1"}' ``` ```json { "api": "https://api.sb/petpantry.shop", "market": { "$id": "https://api.sb/petpantry.shop/markets/market_1", "$type": "Market", "countries": [ "Example countries" ], "currency": "USD", "locales": [ "Example locales" ] }, "action": { "$id": "https://api.sb/petpantry.shop/actions/action_1", "operation": "Market.enter", "status": "done" }, "links": { "self": "https://api.sb/petpantry.shop/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const market = await $.Market.enter({ startup: 'startup_1', market: 'market_1' }) ``` **CLI** ```bash npx startup-builder do Market.enter --json '{"startup":"startup_1","market":"market_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Market.enter({ startup: 'startup_1', market: 'market_1' })" } } ``` ## Example A [Startup](/business/nouns/startup) that enters the European Union Market shows [Prices](/business/nouns/price) in euros and translates its [Site](/business/nouns/site) into `de-DE` and `fr-FR`. The Market wakes the VAT and accessibility floor rows. # book URL: /business/nouns/meeting/book · Id: `verb:Meeting.book` · Call: `await $.Meeting.book({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Book schedules a Meeting with a Contact at a time both calendars hold free. Book schedules a [Meeting](/business/nouns/meeting) with a [Contact](/business/nouns/contact) at a time both calendars hold free. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `contact` | [Contact](/business/nouns/contact) | Yes | Who to meet. | | `at` | `datetime` | Yes | When. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `meeting` | [Meeting](/business/nouns/meeting) | Yes | The booked Meeting. | ## Effects - Emits [`Meeting.booked`](/business/events/Meeting.booked). - Performed by the [Sales Engineer](/agents/sales/sales-engineer). ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Meeting.book](/business/nouns/meeting/book) | | The record is not in a state that allows this Verb, so the call is refused. | [`refused`](/code/api/errors/refused) | Read the record, run the Verb that moves it to an allowed state, then retry. | [Meeting.book](/business/nouns/meeting/book) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Book the latest meeting with a contact. ``` **API** ```bash curl -X POST https://api.sb/kilnbakery.com/meetings/book \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"contact":"contact_1","at":"2026-10-22T12:00:00Z"}' ``` ```json { "api": "https://api.sb/kilnbakery.com", "meeting": { "$id": "https://api.sb/kilnbakery.com/meetings/meeting_1", "$type": "Meeting", "at": "2026-10-22T12:00:00Z" }, "action": { "$id": "https://api.sb/kilnbakery.com/actions/action_1", "operation": "Meeting.book", "status": "done" }, "links": { "self": "https://api.sb/kilnbakery.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const meeting = await $.Meeting.book({ contact: 'contact_1', at: '2026-10-22T12:00:00Z' }) ``` **CLI** ```bash npx startup-builder do Meeting.book --json '{"contact":"contact_1","at":"2026-10-22T12:00:00Z"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Meeting.book({ contact: 'contact_1', at: '2026-10-22T12:00:00Z' })" } } ``` Guides that call it: [Qualify leads and book demos](/workflows/guides/qualify-leads-and-book-demos). # Meeting URL: /business/nouns/meeting · Id: `noun:meeting` > A Meeting is a scheduled time when Workers and Contacts meet about one or more Things, producing notes, Decisions, and Tasks. A Meeting is a scheduled time when [Workers](/business/nouns/worker) and [Contacts](/business/nouns/contact) meet about one or more [Things](/business/nouns/thing), producing notes, [Decisions](/business/nouns/decision), and [Tasks](/business/nouns/task). ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `at` | `datetime` | Yes | When it starts. | | `agenda` | `text` | No | What it covers. | | `transcript` | `text` | No | What was said. | ## Object ```json { "$id": "https://api.sb/ledgerlark.com/meetings/meeting_1", "$type": "Meeting", "at": "2026-10-22T12:00:00Z", "agenda": "Example agenda", "transcript": "Example transcript" } ``` ## Relationships - A Meeting **advances** one [Deal](/business/nouns/deal): a Meeting moves one [Deal](/business/nouns/deal) forward. `advances`, inverse [`meetings`](/business/nouns/deal#rel-meetings). - A Meeting **produces** many [Decisions](/business/nouns/decision): a Meeting records [Decisions](/business/nouns/decision), each with its options, choice and reason. `produces`, inverse [`madeIn`](/business/nouns/decision#rel-made-in). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Meeting.book](/business/nouns/meeting/book) | Book schedules a Meeting with a Contact at a time both calendars hold free. | [Sales Engineer](/agents/sales/sales-engineer) | [`Meeting.booked`](/business/events/Meeting.booked) | None. | | [Meeting.create](/business/nouns/meeting/create) | Creates a Meeting. Inherited from [Noun](/business/nouns/noun). | None. | `Meeting.created` | Two-way: `try`, `send`, `do` | | [Meeting.get](/business/nouns/meeting/get) | Returns one Meeting by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Meeting.list](/business/nouns/meeting/list) | Returns Meetings, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Meeting.update](/business/nouns/meeting/update) | Changes the given properties of a Meeting. Inherited from [Noun](/business/nouns/noun). | None. | `Meeting.updated` | Two-way: `try`, `send`, `do` | | [Meeting.delete](/business/nouns/meeting/delete) | Deletes a Meeting; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Meeting.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Meeting.create` | Yes | Yes | Yes | No | | `Meeting.get` | Yes | Yes | Yes | Yes | | `Meeting.list` | Yes | Yes | Yes | Yes | | `Meeting.update` | Yes | Yes | Yes | No | | `Meeting.delete` | Yes | Yes | Yes | No | | `Meeting.book` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Book the latest meeting with a contact. ``` **API** ```bash curl -X POST https://api.sb/kilnbakery.com/meetings/book \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"contact":"contact_1","at":"2026-10-22T12:00:00Z"}' ``` ```json { "api": "https://api.sb/kilnbakery.com", "meeting": { "$id": "https://api.sb/kilnbakery.com/meetings/meeting_1", "$type": "Meeting", "at": "2026-10-22T12:00:00Z" }, "action": { "$id": "https://api.sb/kilnbakery.com/actions/action_1", "operation": "Meeting.book", "status": "done" }, "links": { "self": "https://api.sb/kilnbakery.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const meeting = await $.Meeting.book({ contact: 'contact_1', at: '2026-10-22T12:00:00Z' }) ``` **CLI** ```bash npx startup-builder do Meeting.book --json '{"contact":"contact_1","at":"2026-10-22T12:00:00Z"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Meeting.book({ contact: 'contact_1', at: '2026-10-22T12:00:00Z' })" } } ``` ## Example A 30-minute Meeting about a county planning firm's [Deal](/business/nouns/deal) produces a transcript, a [Decision](/business/nouns/decision) to pilot one county, and a Task to send a [Quote](/business/nouns/quote). # deactivate URL: /business/nouns/member-directory/deactivate · Id: `verb:MemberDirectory.deactivate` · Call: `await $.MemberDirectory.deactivate({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Deactivate stops a Member Directory’s pushes; everyone it added keeps their Roles until an admin removes them. Deactivate stops a [Member Directory](/business/nouns/member-directory)’s pushes; the people it added keep their [Roles](/business/nouns/role) until an admin removes them. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `directory` | [Member Directory](/business/nouns/member-directory) | Yes | The Member Directory to turn off. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `directory` | [Member Directory](/business/nouns/member-directory) | Yes | The Member Directory, now `inactive`. | ## Effects - Emits [`MemberDirectory.deactivated`](/business/events/MemberDirectory.deactivated). - Performed by the [Security Engineer](/agents/engineering/security-engineer). - Two-way: it runs at once, in the `try`, `send` and `do` modes. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [MemberDirectory.deactivate](/business/nouns/member-directory/deactivate) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Deactivate the latest member directory. ``` **API** ```bash curl -X POST https://api.sb/ledgerlark.com/member-directories/member_directory_1/deactivate \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/ledgerlark.com", "directory": { "$id": "https://api.sb/ledgerlark.com/member-directories/member_directory_1", "$type": "MemberDirectory", "state": "draft" }, "action": { "$id": "https://api.sb/ledgerlark.com/actions/action_1", "operation": "MemberDirectory.deactivate", "status": "done" }, "links": { "self": "https://api.sb/ledgerlark.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const directory = await $.MemberDirectory.deactivate({ directory: 'member_directory_1' }) ``` **CLI** ```bash npx startup-builder do MemberDirectory.deactivate --json '{"directory":"member_directory_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.MemberDirectory.deactivate({ directory: 'member_directory_1' })" } } ``` # deprovision URL: /business/nouns/member-directory/deprovision · Id: `verb:MemberDirectory.deprovision` · Call: `await $.MemberDirectory.deprovision({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Deprovision ends one person’s access to a Tenant in one Action when the Customer’s directory removes them. Deprovision ends one person’s access to a [Tenant](/business/nouns/tenant) in one [Action](/business/nouns/action) when the [Customer](/business/nouns/customer)’s directory removes them. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `directory` | [Member Directory](/business/nouns/member-directory) | Yes | The Member Directory that removed the person. | | `person` | [Person](/business/nouns/person) | Yes | The person removed. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `person` | [Person](/business/nouns/person) | Yes | The person, with no Role left in the Tenant. | | `memberDirectory` | [Member Directory](/business/nouns/member-directory) | Yes | The Member Directory that removed the person. | ## Effects - Emits [`MemberDirectory.deprovisioned`](/business/events/MemberDirectory.deprovisioned). - Performed by the [Security Engineer](/agents/engineering/security-engineer). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Revokes the person’s keys, sign-ins and Mandates in the Tenant before their next call. - Keeps every record the person made, owned by the Tenant. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [MemberDirectory.deprovision](/business/nouns/member-directory/deprovision) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Deprovision the latest member directory with a person. ``` **API** ```bash curl -X POST https://api.sb/shiftnote.app/member-directories/member_directory_1/deprovision \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"person":"person_1"}' ``` ```json { "api": "https://api.sb/shiftnote.app", "person": { "$id": "https://api.sb/shiftnote.app/people/person_1", "$type": "Person", "name": "Daniel Okafor" }, "memberDirectory": { "$id": "https://api.sb/shiftnote.app/member-directories/member_directory_1", "$type": "MemberDirectory", "state": "draft" }, "action": { "$id": "https://api.sb/shiftnote.app/actions/action_1", "operation": "MemberDirectory.deprovision", "status": "done" }, "links": { "self": "https://api.sb/shiftnote.app/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { person, memberDirectory } = await $.MemberDirectory.deprovision({ directory: 'member_directory_1', person: 'person_1' }) ``` **CLI** ```bash npx startup-builder do MemberDirectory.deprovision --json '{"directory":"member_directory_1","person":"person_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.MemberDirectory.deprovision({ directory: 'member_directory_1', person: 'person_1' })" } } ``` # Member Directory URL: /business/nouns/member-directory · Id: `noun:member-directory` > A Member Directory is a Customer’s own list of people and groups, pushed into its Tenant so access follows employment. A Member Directory is a [Customer](/business/nouns/customer)’s own list of people and groups, pushed into its [Tenant](/business/nouns/tenant) so access follows employment. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `state` | `string` | Yes | Where it stands; only `active` fills Roles. | | `groupRoles` | `json` | No | Which directory group fills which Role in the Tenant. | | `lastChangeAt` | `datetime` | No | When the Customer’s directory last pushed a change. | ## Object ```json { "$id": "https://api.sb/kilnbakery.com/member-directories/member_directory_1", "$type": "MemberDirectory", "state": "draft", "groupRoles": {}, "lastChangeAt": "2026-10-22T12:00:00Z" } ``` ## Relationships - A Member Directory **provisions** one [Tenant](/business/nouns/tenant): a Member Directory fills and empties [Roles](/business/nouns/role) in one [Tenant](/business/nouns/tenant) as people join and leave the [Customer](/business/nouns/customer). `provisions`, inverse [`provisionedBy`](/business/nouns/tenant#rel-provisioned-by). ## Lifecycle | State | Meaning | Moves to | | --- | --- | --- | | `draft` (first) | Waiting for the Customer’s directory to connect. | `active` by [MemberDirectory.provision](/business/nouns/member-directory/provision) | | `active` | The Customer’s directory pushes every hire, change and departure, and its groups fill Roles. | `failing` on [`MemberDirectory.failed`](/business/nouns/member-directory#memberdirectoryfailed); `inactive` by [MemberDirectory.deactivate](/business/nouns/member-directory/deactivate) | | `failing` | Pushes stopped arriving or are refused, so access no longer follows the directory. | `active` by [MemberDirectory.provision](/business/nouns/member-directory/provision); `inactive` by [MemberDirectory.deactivate](/business/nouns/member-directory/deactivate) | | `inactive` | Turned off: everyone it added keeps their Roles until an admin removes them. | `active` by [MemberDirectory.provision](/business/nouns/member-directory/provision) | ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [MemberDirectory.deactivate](/business/nouns/member-directory/deactivate) | Deactivate stops a Member Directory’s pushes; everyone it added keeps their Roles until an admin removes them. | [Security Engineer](/agents/engineering/security-engineer) | [`MemberDirectory.deactivated`](/business/events/MemberDirectory.deactivated) | Two-way: `try`, `send`, `do` | | [MemberDirectory.deprovision](/business/nouns/member-directory/deprovision) | Deprovision ends one person’s access to a Tenant in one Action when the Customer’s directory removes them. | [Security Engineer](/agents/engineering/security-engineer) | [`MemberDirectory.deprovisioned`](/business/events/MemberDirectory.deprovisioned) | Two-way: `try`, `send`, `do` | | [MemberDirectory.provision](/business/nouns/member-directory/provision) | Provision starts a Customer’s Member Directory pushing people and groups into its Tenant, with groups mapped to Roles. | [Security Engineer](/agents/engineering/security-engineer) | [`MemberDirectory.provisioned`](/business/events/MemberDirectory.provisioned) | Two-way: `try`, `send`, `do` | | [MemberDirectory.create](/business/nouns/member-directory/create) | Creates a Member Directory. Inherited from [Noun](/business/nouns/noun). | None. | `MemberDirectory.created` | Two-way: `try`, `send`, `do` | | [MemberDirectory.get](/business/nouns/member-directory/get) | Returns one Member Directory by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [MemberDirectory.list](/business/nouns/member-directory/list) | Returns Member Directories, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [MemberDirectory.update](/business/nouns/member-directory/update) | Changes the given properties of a Member Directory. Inherited from [Noun](/business/nouns/noun). | None. | `MemberDirectory.updated` | Two-way: `try`, `send`, `do` | ## Events Events no Verb emits. Each Verb’s Event is in the Verbs table above; every Event is delivered in the same shape. ### MemberDirectory.failed A Customer’s directory stopped pushing, or its pushes are refused, so access no longer follows it. Raised by the rail. | Field | Type | Required | Description | | --- | --- | --- | --- | | `name` | `string` | Yes | `MemberDirectory.failed`. | | `at` | `datetime` | Yes | When it happened. | | `seq` | `integer` | No | Its position in the namespace, one more than the Event before; any seq is a cursor into the history. | | `data` | `json` | Yes | The Thing as the Action left it. | | `data.memberDirectory` | [Member Directory](/business/nouns/member-directory) | Yes | The Member Directory as the change left it. | | `data.memberDirectory.state` | `string` | Yes | Where it stands; only `active` fills Roles. | | `data.memberDirectory.groupRoles` | `json` | No | Which directory group fills which Role in the Tenant. | | `data.memberDirectory.lastChangeAt` | `datetime` | No | When the Customer’s directory last pushed a change. | | `data.cause` | `string` | Yes | What failed: `tokenRevoked`, `noPushIn24h`, or `pushRefused`. | | `data.previous.state` | `string` | Yes | The `state` before this Event: `active`. | ```json { "$id": "https://api.sb/kilnbakery.com/events/event_1", "$type": "Event", "name": "MemberDirectory.failed", "at": "2026-10-22T12:00:00Z", "data": { "memberDirectory": { "$id": "https://api.sb/kilnbakery.com/member-directories/member_directory_1", "$type": "MemberDirectory", "state": "failing", "groupRoles": {}, "lastChangeAt": "2026-10-22T12:00:00Z" }, "cause": "tokenRevoked", "previous": { "state": "active" } }, "seq": 1 } ``` ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `MemberDirectory.create` | Yes | Yes | No | No | | `MemberDirectory.get` | Yes | Yes | Yes | Yes | | `MemberDirectory.list` | Yes | Yes | Yes | Yes | | `MemberDirectory.update` | Yes | Yes | No | No | | `MemberDirectory.deactivate` | Yes | Yes | No | No | | `MemberDirectory.deprovision` | Yes | Yes | No | No | | `MemberDirectory.provision` | Yes | Yes | No | No | ## Call it **Ask** ```text Provision the latest member directory with a tenant. ``` **API** ```bash curl -X POST https://api.sb/tutorloop.com/member-directories/provision \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"tenant":"tenant_1"}' ``` ```json { "api": "https://api.sb/tutorloop.com", "directory": { "$id": "https://api.sb/tutorloop.com/member-directories/member_directory_1", "$type": "MemberDirectory", "state": "draft" }, "action": { "$id": "https://api.sb/tutorloop.com/actions/action_1", "operation": "MemberDirectory.provision", "status": "done" }, "links": { "self": "https://api.sb/tutorloop.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const directory = await $.MemberDirectory.provision({ tenant: 'tenant_1' }) ``` **CLI** ```bash npx startup-builder do MemberDirectory.provision --json '{"tenant":"tenant_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.MemberDirectory.provision({ tenant: 'tenant_1' })" } } ``` ## Example A 400-person [Customer](/business/nouns/customer) pushes its staff directory into its [Tenant](/business/nouns/tenant). The `finance` group fills the [Role](/business/nouns/role) that approves [Bills](/business/nouns/bill), and a person who leaves loses access the same hour. # provision URL: /business/nouns/member-directory/provision · Id: `verb:MemberDirectory.provision` · Call: `await $.MemberDirectory.provision({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Provision starts a Customer’s Member Directory pushing people and groups into its Tenant, with groups mapped to Roles. Provision starts a [Customer](/business/nouns/customer)’s [Member Directory](/business/nouns/member-directory) pushing people and groups into its [Tenant](/business/nouns/tenant), with groups mapped to [Roles](/business/nouns/role). ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `tenant` | [Tenant](/business/nouns/tenant) | Yes | The Tenant it fills. | | `groupRoles` | `json` | No | Which group fills which Role. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `directory` | [Member Directory](/business/nouns/member-directory) | Yes | The Member Directory, now active. | ## Effects - Emits [`MemberDirectory.provisioned`](/business/events/MemberDirectory.provisioned). - Performed by the [Security Engineer](/agents/engineering/security-engineer). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Fills Roles for every person in a mapped group. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [MemberDirectory.provision](/business/nouns/member-directory/provision) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Provision the latest member directory with a tenant. ``` **API** ```bash curl -X POST https://api.sb/tutorloop.com/member-directories/provision \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"tenant":"tenant_1"}' ``` ```json { "api": "https://api.sb/tutorloop.com", "directory": { "$id": "https://api.sb/tutorloop.com/member-directories/member_directory_1", "$type": "MemberDirectory", "state": "draft" }, "action": { "$id": "https://api.sb/tutorloop.com/actions/action_1", "operation": "MemberDirectory.provision", "status": "done" }, "links": { "self": "https://api.sb/tutorloop.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const directory = await $.MemberDirectory.provision({ tenant: 'tenant_1' }) ``` **CLI** ```bash npx startup-builder do MemberDirectory.provision --json '{"tenant":"tenant_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.MemberDirectory.provision({ tenant: 'tenant_1' })" } } ``` # Memory URL: /business/nouns/memory · Id: `noun:memory` > A Memory is a Worker’s own Collection of what it has learned and kept, read by its Functions. A Memory is a [Worker](/business/nouns/worker)’s own [Collection](/business/nouns/collection) of what it has learned and kept, read by its [Functions](/business/nouns/function). ## Properties
Inherited from [Collection](/business/nouns/collection): 1 property | Property | Type | Required | Description | | --- | --- | --- | --- | | `query` | `json` | No | The saved query that defines a dynamic Collection. |
Inherited from [Thing](/business/nouns/thing): 4 properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `id` | `string` | Yes | The stable identifier, which never changes. | | `type` | list of [Noun](/business/nouns/noun) | Yes | The Nouns this Thing is an instance of. | | `state` | `string` | No | The current state in its lifecycle. | | `outside` | `json` | No | The ids this Thing has in outside tools, one per Integration, so a re-run matches instead of duplicating. |
## Object ```json { "$id": "https://api.sb/shiftnote.app/memories/memory_1", "$type": "Memory", "id": "Example id", "type": [ "noun_1" ], "state": "Example state", "outside": {}, "query": {} } ``` ## Relationships - A Memory **is held by** one [Worker](/business/nouns/worker): a [Worker](/business/nouns/worker)’s own Memory of what it has learned, read by its [Functions](/business/nouns/function) and kept within its [Startup](/business/nouns/startup). `heldBy`, inverse [`remembers`](/business/nouns/worker#rel-remembers). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Memory.create](/business/nouns/memory/create) | Creates a Memory. Inherited from [Noun](/business/nouns/noun). | None. | `Memory.created` | Two-way: `try`, `send`, `do` | | [Memory.get](/business/nouns/memory/get) | Returns one Memory by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Memory.list](/business/nouns/memory/list) | Returns Memories, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Memory.update](/business/nouns/memory/update) | Changes the given properties of a Memory. Inherited from [Noun](/business/nouns/noun). | None. | `Memory.updated` | Two-way: `try`, `send`, `do` | | [Memory.delete](/business/nouns/memory/delete) | Deletes a Memory; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Memory.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Memory.create` | Yes | Yes | Yes | No | | `Memory.get` | Yes | Yes | Yes | Yes | | `Memory.list` | Yes | Yes | Yes | Yes | | `Memory.update` | Yes | Yes | Yes | No | | `Memory.delete` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Add a memory to RouteWise with a noun. ``` **API** ```bash curl -X POST https://api.sb/routewise.dev/memories \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"id":"memory_1","type":["noun_1"]}' ``` ```json { "api": "https://api.sb/routewise.dev", "memory": { "$id": "https://api.sb/routewise.dev/memories/memory_1", "$type": "Memory", "id": "Example id", "type": [ "noun_1" ] }, "action": { "$id": "https://api.sb/routewise.dev/actions/action_1", "operation": "Memory.create", "status": "done" }, "links": { "self": "https://api.sb/routewise.dev/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const memory = await $.Memory.create({ id: 'memory_1', type: ['noun_1'] }) ``` **CLI** ```bash npx startup-builder do Memory.create --json '{"id":"memory_1","type":["noun_1"]}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Memory.create({ id: 'memory_1', type: ['noun_1'] })" } } ``` ## Example The Memory of Sienna, the [Success Manager](/agents/customer/success-manager) of a meal-planning [App](/business/nouns/app), holds that one household skips weekend dinners and dislikes cilantro. Her [Functions](/business/nouns/function) read both before each suggestion. # broadcast URL: /business/nouns/message/broadcast · Id: `verb:Message.broadcast` · Call: `await $.Message.broadcast({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Broadcast sends one Message to an Audience, now or at a set time, split by Variant when an Experiment runs. Broadcast sends one [Message](/business/nouns/message) to an [Audience](/business/nouns/audience), now or at a set time, split by [Variant](/business/nouns/variant) when an [Experiment](/business/nouns/experiment) runs. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `message` | [Message](/business/nouns/message) | Yes | The Message to send. | | `audience` | [Audience](/business/nouns/audience) | Yes | Who receives it. | | `at` | `datetime` | No | When it goes out; omitted, now. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `messages` | list of [Message](/business/nouns/message) | Yes | One sent Message per Contact. | | `message` | [Message](/business/nouns/message) | Yes | The Message broadcast. | ## Effects - Emits [`Message.broadcasted`](/business/events/Message.broadcasted). - Performed by the [Marketing Lead](/agents/marketing/marketing-lead). - One-way (brand, customer): it waits out its delay window, and runs in the `send` and `do` modes. - Skips every Contact without Consent for the topic or on a Suppression. - Sends from the broadcast stream, never the Domain receipts use. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Message.broadcast](/business/nouns/message/broadcast) | ## When it waits | Gate | Default | | --- | --- | | Decision class | High: one-way, broad (brand, customer) | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | 1 business day, in which a watcher can pause, redirect or cancel it; then it runs. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Broadcast the latest message with an audience. ``` **API** ```bash curl -X POST https://api.sb/kilnbakery.com/messages/message_1/broadcast \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"audience":"audience_1"}' ``` ```json { "api": "https://api.sb/kilnbakery.com", "messages": [ { "$id": "https://api.sb/kilnbakery.com/messages/message_1", "$type": "Message", "medium": "email", "direction": "inbound", "body": "Example body" } ], "message": { "$id": "https://api.sb/kilnbakery.com/messages/message_1", "$type": "Message", "medium": "email", "direction": "inbound", "body": "Example body" }, "action": { "$id": "https://api.sb/kilnbakery.com/actions/action_1", "operation": "Message.broadcast", "status": "done" }, "links": { "self": "https://api.sb/kilnbakery.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { messages, message } = await $.Message.broadcast({ message: 'message_1', audience: 'audience_1' }) ``` **CLI** ```bash npx startup-builder do Message.broadcast --json '{"message":"message_1","audience":"audience_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Message.broadcast({ message: 'message_1', audience: 'audience_1' })" } } ``` # Message URL: /business/nouns/message · Id: `noun:message` > A Message is one communication from any party over one medium, such as email, SMS, or chat, inbound or outbound. A Message is one communication from any party over one medium, such as email, SMS, or chat, inbound or outbound. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `medium` | `string` | Yes | One of `email`, `sms`, `voice`, or `chat`. | | `direction` | `string` | Yes | One of `inbound` or `outbound`. | | `body` | `text` | Yes | What it says. | | `from` | `string` | No | The sender: an address, a number, or a Channel id. | | `to` | `string` | No | The recipient: an address, a number, or a Person id. | | `subject` | `string` | No | The subject line, for email. | | `purpose` | `string` | No | Why it goes out, such as onboarding; consent and suppression rules read it. | ## Object ```json { "$id": "https://api.sb/routewise.dev/messages/message_1", "$type": "Message", "medium": "email", "direction": "inbound", "body": "Example body", "from": "Example from", "to": "Example to", "subject": "Example subject", "purpose": "Example purpose" } ``` ## Relationships - A Message **is posted in** one [Channel](/business/nouns/channel): every Message flows through one [Channel](/business/nouns/channel). `postedIn`, inverse [`messages`](/business/nouns/channel#rel-messages). - A Message **is scheduled by** one [Sequence](/business/nouns/sequence): a [Sequence](/business/nouns/sequence) sends Messages, each at its own step and wait. `scheduledBy`, inverse [`schedules`](/business/nouns/sequence#rel-schedules). - A Message **is screened by** many [Guards](/business/nouns/guard): [Guards](/business/nouns/guard) check every outbound Message before it goes out. `screenedBy`, inverse [`screens`](/business/nouns/guard#rel-screens). - A Message **has** one [Thread](/business/nouns/thread): a [Thread](/business/nouns/thread) groups Messages that reply to one another. `thread`, inverse [`groups`](/business/nouns/thread#rel-groups). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Message.broadcast](/business/nouns/message/broadcast) | Broadcast sends one Message to an Audience, now or at a set time, split by Variant when an Experiment runs. | [Marketing Lead](/agents/marketing/marketing-lead) | [`Message.broadcasted`](/business/events/Message.broadcasted) | One-way (brand, customer): `send`, `do` | | [Message.schedule](/business/nouns/message/schedule) | Schedule holds a Message until a set time and sends it then, unless it is canceled first. | [Marketing Lead](/agents/marketing/marketing-lead) | [`Message.scheduled`](/business/events/Message.scheduled) | Two-way: `try`, `send`, `do` | | [Message.create](/business/nouns/message/create) | Creates a Message. Inherited from [Noun](/business/nouns/noun). | None. | `Message.created` | Two-way: `try`, `send`, `do` | | [Message.get](/business/nouns/message/get) | Returns one Message by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Message.list](/business/nouns/message/list) | Returns Messages, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Message.update](/business/nouns/message/update) | Changes the given properties of a Message. Inherited from [Noun](/business/nouns/noun). | None. | `Message.updated` | Two-way: `try`, `send`, `do` | | [Message.delete](/business/nouns/message/delete) | Deletes a Message; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Message.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Message.create` | Yes | Yes | Yes | No | | `Message.get` | Yes | Yes | Yes | Yes | | `Message.list` | Yes | Yes | Yes | Yes | | `Message.update` | Yes | Yes | Yes | No | | `Message.delete` | Yes | Yes | Yes | No | | `Message.broadcast` | Yes | No | No | No | | `Message.schedule` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Broadcast the latest message with an audience. ``` **API** ```bash curl -X POST https://api.sb/kilnbakery.com/messages/message_1/broadcast \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"audience":"audience_1"}' ``` ```json { "api": "https://api.sb/kilnbakery.com", "messages": [ { "$id": "https://api.sb/kilnbakery.com/messages/message_1", "$type": "Message", "medium": "email", "direction": "inbound", "body": "Example body" } ], "message": { "$id": "https://api.sb/kilnbakery.com/messages/message_1", "$type": "Message", "medium": "email", "direction": "inbound", "body": "Example body" }, "action": { "$id": "https://api.sb/kilnbakery.com/actions/action_1", "operation": "Message.broadcast", "status": "done" }, "links": { "self": "https://api.sb/kilnbakery.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { messages, message } = await $.Message.broadcast({ message: 'message_1', audience: 'audience_1' }) ``` **CLI** ```bash npx startup-builder do Message.broadcast --json '{"message":"message_1","audience":"audience_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Message.broadcast({ message: 'message_1', audience: 'audience_1' })" } } ``` ## Example A text from a parent asking to move tomorrow's tutoring session is one inbound Message. The tutor's reply in the same [Thread](/business/nouns/thread) is another, outbound. # schedule URL: /business/nouns/message/schedule · Id: `verb:Message.schedule` · Call: `await $.Message.schedule({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Schedule holds a Message until a set time and sends it then, unless it is canceled first. Schedule holds a [Message](/business/nouns/message) until a set time and sends it then, unless it is canceled first. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `message` | [Message](/business/nouns/message) | Yes | The Message to hold. | | `at` | `datetime` | Yes | When it goes out. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `message` | [Message](/business/nouns/message) | Yes | The scheduled Message. | ## Effects - Emits [`Message.scheduled`](/business/events/Message.scheduled). - Performed by the [Marketing Lead](/agents/marketing/marketing-lead). - Two-way: it runs at once, in the `try`, `send` and `do` modes. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Message.schedule](/business/nouns/message/schedule) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Schedule the latest message. ``` **API** ```bash curl -X POST https://api.sb/tutorloop.com/messages/message_1/schedule \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"at":"2026-10-22T12:00:00Z"}' ``` ```json { "api": "https://api.sb/tutorloop.com", "message": { "$id": "https://api.sb/tutorloop.com/messages/message_1", "$type": "Message", "medium": "email", "direction": "inbound", "body": "Example body" }, "action": { "$id": "https://api.sb/tutorloop.com/actions/action_1", "operation": "Message.schedule", "status": "done" }, "links": { "self": "https://api.sb/tutorloop.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const message = await $.Message.schedule({ message: 'message_1', at: '2026-10-22T12:00:00Z' }) ``` **CLI** ```bash npx startup-builder do Message.schedule --json '{"message":"message_1","at":"2026-10-22T12:00:00Z"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Message.schedule({ message: 'message_1', at: '2026-10-22T12:00:00Z' })" } } ``` # Meter URL: /business/nouns/meter · Id: `noun:meter` > A Meter is a billable measure of usage that turns usage Events into Entries exactly once. A Meter is a billable measure of usage that turns usage [Events](/business/nouns/event) into [Entries](/business/nouns/entry) exactly once. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `unit` | `string` | Yes | What it counts, such as calls or tokens. | | `of` | `string` | Yes | The declared Event the Meter counts. | | `aggregation` | `string` | Yes | How counted Events combine over the window: a sum of a value, a count, or the last value. | | `window` | `string` | Yes | The period usage accrues over before it bills, such as a month. | ## Object ```json { "$id": "https://api.sb/ledgerlark.com/meters/meter_1", "$type": "Meter", "unit": "call", "of": "Reminder.sent", "aggregation": "sum", "window": "month" } ``` ## Relationships - A Meter **counts** many [Events](/business/nouns/event): the [Events](/business/nouns/event) the Meter counts toward usage billing. `counts`, inverse [`meteredBy`](/business/nouns/event#rel-metered-by). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Meter.create](/business/nouns/meter/create) | Creates a Meter. Inherited from [Noun](/business/nouns/noun). | None. | `Meter.created` | Two-way: `try`, `send`, `do` | | [Meter.get](/business/nouns/meter/get) | Returns one Meter by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Meter.list](/business/nouns/meter/list) | Returns Meters, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Meter.update](/business/nouns/meter/update) | Changes the given properties of a Meter. Inherited from [Noun](/business/nouns/noun). | None. | `Meter.updated` | Two-way: `try`, `send`, `do` | | [Meter.delete](/business/nouns/meter/delete) | Deletes a Meter; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Meter.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Meter.create` | Yes | Yes | Yes | No | | `Meter.get` | Yes | Yes | Yes | Yes | | `Meter.list` | Yes | Yes | Yes | Yes | | `Meter.update` | Yes | Yes | Yes | No | | `Meter.delete` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Add a meter to PatentPad. ``` **API** ```bash curl -X POST https://api.sb/patentpad.com/meters \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"unit":"call","of":"Reminder.sent","aggregation":"sum","window":"month"}' ``` ```json { "api": "https://api.sb/patentpad.com", "meter": { "$id": "https://api.sb/patentpad.com/meters/meter_1", "$type": "Meter", "unit": "call", "of": "Reminder.sent", "aggregation": "sum", "window": "month" }, "action": { "$id": "https://api.sb/patentpad.com/actions/action_1", "operation": "Meter.create", "status": "done" }, "links": { "self": "https://api.sb/patentpad.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const meter = await $.Meter.create({ unit: 'call', of: 'Reminder.sent', aggregation: 'sum', window: 'month' }) ``` **CLI** ```bash npx startup-builder do Meter.create --json '{"unit":"call","of":"Reminder.sent","aggregation":"sum","window":"month"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Meter.create({ unit: 'call', of: 'Reminder.sent', aggregation: 'sum', window: 'month' })" } } ``` ## Example The `reminder` Meter of a clinic-reminder [SaaS](/products/templates/saas) counts each `Reminder.sent` [Event](/business/nouns/event) once and posts one [Entry](/business/nouns/entry) per reminder at $0.03. # define URL: /business/nouns/metric/define · Id: `verb:Metric.define` · Call: `await $.Metric.define({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Define compiles a Metric’s query against the Startup’s Events and Entries and lists every Event it reads. Define compiles a [Metric](/business/nouns/metric)’s query against the [Startup](/business/nouns/startup)’s [Events](/business/nouns/event) and [Entries](/business/nouns/entry) and lists every Event it reads. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `name` | `string` | Yes | The Metric’s name. | | `query` | `text` | Yes | The query, over Events and Entries. | | `unit` | `string` | Yes | What one unit of it is. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `metric` | [Metric](/business/nouns/metric) | Yes | The defined Metric. | ## Effects - Emits [`Metric.defined`](/business/events/Metric.defined). - Performed by the [Analyst](/agents/marketing/analyst). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - A Change that renames or removes an Event this Metric reads must map it to a new Event, or the Change is refused. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Metric.define](/business/nouns/metric/define) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Define the latest metric. ``` **API** ```bash curl -X POST https://api.sb/ledgerlark.com/metrics/define \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"name":"LedgerLark","query":"Example query","unit":"Example unit"}' ``` ```json { "api": "https://api.sb/ledgerlark.com", "metric": { "$id": "https://api.sb/ledgerlark.com/metrics/metric_1", "$type": "Metric", "query": "Example query", "status": "draft" }, "action": { "$id": "https://api.sb/ledgerlark.com/actions/action_1", "operation": "Metric.define", "status": "done" }, "links": { "self": "https://api.sb/ledgerlark.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const metric = await $.Metric.define({ name: 'LedgerLark', query: 'Example query', unit: 'Example unit' }) ``` **CLI** ```bash npx startup-builder do Metric.define --json '{"name":"LedgerLark","query":"Example query","unit":"Example unit"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Metric.define({ name: 'LedgerLark', query: 'Example query', unit: 'Example unit' })" } } ``` # Metric URL: /business/nouns/metric · Id: `noun:metric` > A Metric is a named measure computed from Events or Entries, always derived and never typed in. A Metric is a named measure computed from [Events](/business/nouns/event) or [Entries](/business/nouns/entry), always derived and never typed in. [Key Results](/business/nouns/key-result), [Experiments](/business/nouns/experiment) and [Dashboards](/business/nouns/dashboard) read the same Metric, so one number means one thing. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `query` | `text` | Yes | How it is computed. An agent never varies the Metrics it is judged by. Never randomized. | | `unit` | `string` | No | The unit, such as dollars or percent. | | `status` | `string` | Yes | One of `draft` or `defined`. | ## Object ```json { "$id": "https://api.sb/kilnbakery.com/metrics/metric_1", "$type": "Metric", "query": "Example query", "unit": "Example unit", "status": "draft" } ``` ## Relationships - A Metric **is computed from** many [Events](/business/nouns/event): a Metric derives from [Events](/business/nouns/event) and is never typed in. `computedFrom`, inverse [`feeds`](/business/nouns/event#rel-feeds). - A Metric **is computed under** many [Policies](/business/nouns/policy): a [Policy](/business/nouns/policy) rules how Metrics are computed, such as revenue under revenue recognition. `computedUnder`, inverse [`computes`](/business/nouns/policy#rel-computes). - A Metric **is informed by** many [Surveys](/business/nouns/survey): [Survey](/business/nouns/survey) answers compute Metrics, such as a satisfaction score. `informedBy`, inverse [`informs`](/business/nouns/survey#rel-informs). - A Metric **is measured by** many [Experiments](/business/nouns/experiment): one primary Metric judges an [Experiment](/business/nouns/experiment)’s [Variants](/business/nouns/variant); guardrail Metrics stop it. `measuredBy`, inverse [`measures`](/business/nouns/experiment#rel-measures). - A Metric **is moved by** many [Plays](/business/nouns/play): a [Play](/business/nouns/play) exists to move named Metrics, read before and after every run. `movedBy`, inverse [`moves`](/business/nouns/play#rel-moves). - A Metric **read by** many [Key Results](/business/nouns/key-result): a [Key Result](/business/nouns/key-result) compares one Metric’s value against its baseline and target. `readBy`, inverse [`reads`](/business/nouns/key-result#rel-reads). - A Metric **is shown on** many [Dashboards](/business/nouns/dashboard): a [Dashboard](/business/nouns/dashboard) reads out Metrics, each computed from [Events](/business/nouns/event) and never typed in. `shownOn`, inverse [`shows`](/business/nouns/dashboard#rel-shows). ## Lifecycle | State | Meaning | Moves to | | --- | --- | --- | | `draft` (first) | Its query is written and not compiled, so nothing reads it. | `defined` by [Metric.define](/business/nouns/metric/define) | | `defined` | Its query compiles against the Startup’s Events and Entries; defining it again recompiles an edited query. | None: it ends here. | ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Metric.define](/business/nouns/metric/define) | Define compiles a Metric’s query against the Startup’s Events and Entries and lists every Event it reads. | [Analyst](/agents/marketing/analyst) | [`Metric.defined`](/business/events/Metric.defined) | Two-way: `try`, `send`, `do` | | [Metric.query](/business/nouns/metric/query) | Query reads Metrics or Events as a trend, funnel, retention curve, path or lifecycle, broken down by any property. | [Analyst](/agents/marketing/analyst) | [`Metric.queried`](/business/events/Metric.queried) | Two-way: `try`, `send`, `do` | | [Metric.watch](/business/nouns/metric/watch) | Watch alerts the owner of a Metric when it crosses a threshold, by a Task or a Message. | [Analyst](/agents/marketing/analyst) | [`Metric.watched`](/business/events/Metric.watched) | Two-way: `try`, `send`, `do` | | [Metric.create](/business/nouns/metric/create) | Creates a Metric. Inherited from [Noun](/business/nouns/noun). | None. | `Metric.created` | Two-way: `try`, `send`, `do` | | [Metric.get](/business/nouns/metric/get) | Returns one Metric by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Metric.list](/business/nouns/metric/list) | Returns Metrics, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Metric.update](/business/nouns/metric/update) | Changes the given properties of a Metric. Inherited from [Noun](/business/nouns/noun). | None. | `Metric.updated` | Two-way: `try`, `send`, `do` | | [Metric.delete](/business/nouns/metric/delete) | Deletes a Metric; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Metric.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Metric.create` | Yes | Yes | Yes | No | | `Metric.get` | Yes | Yes | Yes | Yes | | `Metric.list` | Yes | Yes | Yes | Yes | | `Metric.update` | Yes | Yes | Yes | No | | `Metric.delete` | Yes | Yes | Yes | No | | `Metric.define` | Yes | Yes | Yes | No | | `Metric.query` | Yes | Yes | Yes | No | | `Metric.watch` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Define the latest metric. ``` **API** ```bash curl -X POST https://api.sb/ledgerlark.com/metrics/define \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"name":"LedgerLark","query":"Example query","unit":"Example unit"}' ``` ```json { "api": "https://api.sb/ledgerlark.com", "metric": { "$id": "https://api.sb/ledgerlark.com/metrics/metric_1", "$type": "Metric", "query": "Example query", "status": "draft" }, "action": { "$id": "https://api.sb/ledgerlark.com/actions/action_1", "operation": "Metric.define", "status": "done" }, "links": { "self": "https://api.sb/ledgerlark.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const metric = await $.Metric.define({ name: 'LedgerLark', query: 'Example query', unit: 'Example unit' }) ``` **CLI** ```bash npx startup-builder do Metric.define --json '{"name":"LedgerLark","query":"Example query","unit":"Example unit"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Metric.define({ name: 'LedgerLark', query: 'Example query', unit: 'Example unit' })" } } ``` ## Example Monthly recurring revenue is a Metric whose `query` sums active [Subscription](/business/nouns/subscription) Entries, with `unit: USD`. A pricing Experiment, the revenue Dashboard and the annual Key Result all read that one value. # query URL: /business/nouns/metric/query · Id: `verb:Metric.query` · Call: `await $.Metric.query({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Query reads Metrics or Events as a trend, funnel, retention curve, path or lifecycle, broken down by any property. Query reads [Metrics](/business/nouns/metric) or [Events](/business/nouns/event) as a trend, funnel, retention curve, path or lifecycle, broken down by any property. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `metric` | [Metric](/business/nouns/metric) | No | The Metric to read; omitted, the query names Events directly. | | `shape` | `string` | Yes | The analysis to run. | | `breakdown` | `string` | No | The property to split by, such as an Organization or a Motion. | | `window` | `string` | No | The time range, such as `30d`. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `rows` | `json` | Yes | The result rows, each number with its readability. | | `metric` | [Metric](/business/nouns/metric) | Yes | The Metric read. | ## Effects - Emits [`Metric.queried`](/business/events/Metric.queried). - Performed by the [Analyst](/agents/marketing/analyst). - Two-way: it runs at once, in the `try`, `send` and `do` modes. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Metric.query](/business/nouns/metric/query) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Query the latest metric. ``` **API** ```bash curl -X POST https://api.sb/tutorloop.com/metrics/query \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"shape":"trend"}' ``` ```json { "api": "https://api.sb/tutorloop.com", "rows": {}, "metric": { "$id": "https://api.sb/tutorloop.com/metrics/metric_1", "$type": "Metric", "query": "Example query", "status": "draft" }, "action": { "$id": "https://api.sb/tutorloop.com/actions/action_1", "operation": "Metric.query", "status": "done" }, "links": { "self": "https://api.sb/tutorloop.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { rows, metric } = await $.Metric.query({ shape: 'trend' }) ``` **CLI** ```bash npx startup-builder do Metric.query --json '{"shape":"trend"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Metric.query({ shape: 'trend' })" } } ``` # watch URL: /business/nouns/metric/watch · Id: `verb:Metric.watch` · Call: `await $.Metric.watch({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Watch alerts the owner of a Metric when it crosses a threshold, by a Task or a Message. [Watch](/business/nouns/watch) alerts the owner of a [Metric](/business/nouns/metric) when it crosses a threshold, by a [Task](/business/nouns/task) or a [Message](/business/nouns/message). ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `metric` | [Metric](/business/nouns/metric) | Yes | The Metric to watch. | | `threshold` | `number` | Yes | The value that trips it. | | `direction` | `string` | Yes | Trip when the Metric goes above or below the threshold. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `watch` | [Watch](/business/nouns/watch) | Yes | The Watch that checks it. | | `metric` | [Metric](/business/nouns/metric) | Yes | The Metric now watched. | ## Effects - Emits [`Metric.watched`](/business/events/Metric.watched). - Performed by the [Analyst](/agents/marketing/analyst). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - A guardrail Metric that trips stops its Experiment at once, with no delay window. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Metric.watch](/business/nouns/metric/watch) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Watch the latest metric. ``` **API** ```bash curl -X POST https://api.sb/patentpad.com/metrics/metric_1/watch \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"threshold":1,"direction":"above"}' ``` ```json { "api": "https://api.sb/patentpad.com", "watch": { "$id": "https://api.sb/patentpad.com/watches/watch_1", "$type": "Watch", "selector": "Example selector", "url": "https://patentpad.com" }, "metric": { "$id": "https://api.sb/patentpad.com/metrics/metric_1", "$type": "Metric", "query": "Example query", "status": "draft" }, "action": { "$id": "https://api.sb/patentpad.com/actions/action_1", "operation": "Metric.watch", "status": "done" }, "links": { "self": "https://api.sb/patentpad.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { watch, metric } = await $.Metric.watch({ metric: 'metric_1', threshold: 1, direction: 'above' }) ``` **CLI** ```bash npx startup-builder do Metric.watch --json '{"metric":"metric_1","threshold":1,"direction":"above"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Metric.watch({ metric: 'metric_1', threshold: 1, direction: 'above' })" } } ``` # Minimum Success Criteria URL: /business/nouns/minimum-success-criteria · Id: `noun:minimum-success-criteria` > Minimum Success Criteria is the one number a Startup must reach by a date to stay worth running: a Goal the Founder sets once. Minimum Success Criteria is the one number a [Startup](/business/nouns/startup) must reach by a date to stay worth running: a [Goal](/business/nouns/goal) the [Founder](/agents/founding/founder) sets once. At that date, the Startup perseveres or pivots on it. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `metric` | [Metric](/business/nouns/metric) | Yes | The Metric the number is measured in. | | `value` | `number` | Yes | The number to reach. | | `by` | `date` | Yes | The date it must be reached. | | `fermi` | `json` | No | The Price, rates and volumes that show the number is reachable. |
Inherited from [Goal](/business/nouns/goal): 2 properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `objective` | `text` | Yes | The qualitative outcome. | | `horizon` | `string` | No | One of `day`, `week`, `quarter`, `year`, or `three-years`. |
## Object ```json { "$id": "https://api.sb/kilnbakery.com/minimum-success-criteria/minimum_success_criteria_1", "$type": "MinimumSuccessCriteria", "objective": "Example objective", "horizon": "day", "metric": "metric_1", "value": 1, "by": "2026-10-22", "fermi": {} } ``` ## Relationships - The Minimum Success Criteria **is set for** one [Startup](/business/nouns/startup): the one number that decides whether the [Startup](/business/nouns/startup) keeps running. `setFor`, inverse [`mustReach`](/business/nouns/startup#rel-must-reach). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [MinimumSuccessCriteria.create](/business/nouns/minimum-success-criteria/create) | Creates a Minimum Success Criteria. Inherited from [Noun](/business/nouns/noun). | None. | `MinimumSuccessCriteria.created` | Two-way: `try`, `send`, `do` | | [MinimumSuccessCriteria.get](/business/nouns/minimum-success-criteria/get) | Returns one Minimum Success Criteria by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [MinimumSuccessCriteria.list](/business/nouns/minimum-success-criteria/list) | Returns Minimum Success Criteria, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [MinimumSuccessCriteria.update](/business/nouns/minimum-success-criteria/update) | Changes the given properties of a Minimum Success Criteria. Inherited from [Noun](/business/nouns/noun). | None. | `MinimumSuccessCriteria.updated` | Two-way: `try`, `send`, `do` | | [MinimumSuccessCriteria.delete](/business/nouns/minimum-success-criteria/delete) | Deletes a Minimum Success Criteria; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `MinimumSuccessCriteria.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `MinimumSuccessCriteria.create` | Yes | Yes | Yes | No | | `MinimumSuccessCriteria.get` | Yes | Yes | Yes | Yes | | `MinimumSuccessCriteria.list` | Yes | Yes | Yes | Yes | | `MinimumSuccessCriteria.update` | Yes | Yes | Yes | No | | `MinimumSuccessCriteria.delete` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Add a minimum success criteria to QuietCopy with a metric. ``` **API** ```bash curl -X POST https://api.sb/quietcopy.com/minimum-success-criteria \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"objective":"Example objective","metric":"metric_1","value":1,"by":"2026-10-22"}' ``` ```json { "api": "https://api.sb/quietcopy.com", "minimumSuccessCriteria": { "$id": "https://api.sb/quietcopy.com/minimum-success-criteria/minimum_success_criteria_1", "$type": "MinimumSuccessCriteria", "objective": "Example objective", "metric": "metric_1", "value": 1, "by": "2026-10-22" }, "action": { "$id": "https://api.sb/quietcopy.com/actions/action_1", "operation": "MinimumSuccessCriteria.create", "status": "done" }, "links": { "self": "https://api.sb/quietcopy.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const minimumSuccessCriteria = await $.MinimumSuccessCriteria.create({ objective: 'Example objective', metric: 'metric_1', value: 1, by: '2026-10-22' }) ``` **CLI** ```bash npx startup-builder do MinimumSuccessCriteria.create --json '{"objective":"Example objective","metric":"metric_1","value":1,"by":"2026-10-22"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.MinimumSuccessCriteria.create({ objective: 'Example objective', metric: 'metric_1', value: 1, by: '2026-10-22' })" } } ``` ## Example A bookkeeping Startup sets `value: 8000` in monthly revenue from outside [Customers](/business/nouns/customer), `by` its sixth month. Its `fermi` shows the path: 20 Customers at a $400 [Price](/business/nouns/price). # Mode URL: /business/nouns/mode · Id: `noun:mode` > A Mode is how a caller invokes a Verb: try waits and stores nothing, send returns a pending Action, do waits for the result. A Mode is how a caller invokes a [Verb](/business/nouns/verb): try waits and stores nothing, send returns a pending [Action](/business/nouns/action), do waits for the result. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `name` | `string` | Yes | One of `try`, `send`, or `do`. | | `durable` | `boolean` | Yes | True when the Action is stored and survives restarts: `send` and `do`. | | `waits` | `boolean` | Yes | True when the caller holds the call open until the result: `try` and `do`. | | `holdSeconds` | `integer` | No | For `do`: seconds a call holds before it returns `202` with the pending Action; Setting `mode.holdSeconds`. | | `maxWaitSeconds` | `integer` | No | The longest hold `Prefer: wait=N` may ask for; Setting `mode.maxWaitSeconds`. | ## Object ```json { "$id": "https://api.sb/ledgerlark.com/modes/mode_1", "$type": "Mode", "name": "try", "durable": true, "waits": true, "holdSeconds": 60, "maxWaitSeconds": 300 } ``` ## Relationships - A Mode **default for** many [Verbs](/business/nouns/verb): the Mode a call uses when the caller names none: `try`, `send` or `do`. `defaultFor`, inverse [`defaultsTo`](/business/nouns/verb#rel-defaults-to). - A Mode **is a mode of** many [Actions](/business/nouns/action): the Mode the caller chose: `try` stores nothing, `send` returns a pending [Action](/business/nouns/action), `do` waits for the result. `modeOf`, inverse [`runsIn`](/business/nouns/action#rel-runs-in). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Mode.get](/business/nouns/mode/get) | Returns one Mode by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Mode.list](/business/nouns/mode/list) | Returns Modes, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | A Mode is kept forever and never edited: it has no `update` or `delete`. ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Mode.get` | Yes | Yes | Yes | Yes | | `Mode.list` | Yes | Yes | Yes | Yes | ## Call it **Ask** ```text Show me the latest mode. ``` **API** ```bash curl https://api.sb/patentpad.com/modes/mode_1 \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/patentpad.com", "$type": "Mode", "$id": "https://api.sb/patentpad.com/modes/mode_1", "mode": { "$id": "https://api.sb/patentpad.com/modes/mode_1", "$type": "Mode", "name": "try", "durable": true, "waits": true }, "links": { "self": "https://api.sb/patentpad.com/modes/mode_1", "up": "https://api.sb/patentpad.com/modes" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const mode = await $.Mode.get({ id: 'mode_1' }) ``` **CLI** ```bash npx startup-builder do Mode.get --json '{"id":"mode_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Mode.get({ id: 'mode_1' })" } } ``` ## Example ```ts import { $ } from 'startup-builder' const preview = await $.try.Order.place({ offer: 'offer_1' }) // waits, stores nothing const pending = await $.send.Order.place({ offer: 'offer_1' }) // the Action, status Pending const order = await $.do.Order.place({ offer: 'offer_1' }) // waits for the finished Action ``` # check URL: /business/nouns/monitor/check · Id: `verb:Monitor.check` · Call: `await $.Monitor.check({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Check runs a Monitor once now from several regions and records the result as an Event. Check runs a [Monitor](/business/nouns/monitor) once now from several regions and records the result as an [Event](/business/nouns/event). ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `monitor` | [Monitor](/business/nouns/monitor) | Yes | The Monitor to run. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `monitor` | [Monitor](/business/nouns/monitor) | Yes | The Monitor, with its latest result. | ## Effects - Emits [`Monitor.checked`](/business/events/Monitor.checked). - Performed by the [Reliability Engineer](/agents/engineering/reliability-engineer). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - A failing `internal` Monitor opens an Incident. - A failing `outside` Monitor records a signal Event for the Teams that read it. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Monitor.check](/business/nouns/monitor/check) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Check the latest monitor. ``` **API** ```bash curl -X POST https://api.sb/quietcopy.com/monitors/monitor_1/check \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/quietcopy.com", "monitor": { "$id": "https://api.sb/quietcopy.com/monitors/monitor_1", "$type": "Monitor", "kind": "internal", "target": "/health" }, "action": { "$id": "https://api.sb/quietcopy.com/actions/action_1", "operation": "Monitor.check", "status": "done" }, "links": { "self": "https://api.sb/quietcopy.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const monitor = await $.Monitor.check({ monitor: 'monitor_1' }) ``` **CLI** ```bash npx startup-builder do Monitor.check --json '{"monitor":"monitor_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Monitor.check({ monitor: 'monitor_1' })" } } ``` # Monitor URL: /business/nouns/monitor · Id: `noun:monitor` > A Monitor is a scheduled check on something outside a Startup’s control, such as uptime, a Keyword’s rank or an AI answer, recording Events. A Monitor is a scheduled check on something outside a [Startup](/business/nouns/startup)’s control, such as uptime, a [Keyword](/business/nouns/keyword)’s rank or an AI answer, recording [Events](/business/nouns/event). ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `kind` | `string` | Yes | `internal` watches the Startup’s own routes and jobs; `outside` watches the world, such as a rival’s price. | | `target` | `string` | Yes | What it checks: a route, a Domain, a Keyword, a prompt or a page. | | `every` | `string` | No | How often it runs, such as `1m` or `1d`. | | `lastResult` | `string` | No | The result of its latest check. | ## Object ```json { "$id": "https://api.sb/kilnbakery.com/monitors/monitor_1", "$type": "Monitor", "kind": "internal", "target": "/health", "every": "1m", "lastResult": "passing" } ``` ## Relationships - A Monitor **opens** many [Incidents](/business/nouns/incident): a failing internal Monitor opens an [Incident](/business/nouns/incident), which names the Monitor that saw it first. `opens`, inverse [`monitor`](/business/nouns/incident#rel-monitor). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Monitor.check](/business/nouns/monitor/check) | Check runs a Monitor once now from several regions and records the result as an Event. | [Reliability Engineer](/agents/engineering/reliability-engineer) | [`Monitor.checked`](/business/events/Monitor.checked) | Two-way: `try`, `send`, `do` | | [Monitor.create](/business/nouns/monitor/create) | Creates a Monitor. Inherited from [Noun](/business/nouns/noun). | None. | `Monitor.created` | Two-way: `try`, `send`, `do` | | [Monitor.get](/business/nouns/monitor/get) | Returns one Monitor by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Monitor.list](/business/nouns/monitor/list) | Returns Monitors, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Monitor.update](/business/nouns/monitor/update) | Changes the given properties of a Monitor. Inherited from [Noun](/business/nouns/noun). | None. | `Monitor.updated` | Two-way: `try`, `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Monitor.create` | Yes | Yes | Yes | No | | `Monitor.get` | Yes | Yes | Yes | Yes | | `Monitor.list` | Yes | Yes | Yes | Yes | | `Monitor.update` | Yes | Yes | Yes | No | | `Monitor.check` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Check the latest monitor. ``` **API** ```bash curl -X POST https://api.sb/quietcopy.com/monitors/monitor_1/check \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/quietcopy.com", "monitor": { "$id": "https://api.sb/quietcopy.com/monitors/monitor_1", "$type": "Monitor", "kind": "internal", "target": "/health" }, "action": { "$id": "https://api.sb/quietcopy.com/actions/action_1", "operation": "Monitor.check", "status": "done" }, "links": { "self": "https://api.sb/quietcopy.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const monitor = await $.Monitor.check({ monitor: 'monitor_1' }) ``` **CLI** ```bash npx startup-builder do Monitor.check --json '{"monitor":"monitor_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Monitor.check({ monitor: 'monitor_1' })" } } ``` ## Example A scheduling app runs an `outside` Monitor that asks three answer engines "best scheduling app for clinics" once a day. When the app drops out of an answer, the Monitor records an [Event](/business/nouns/event) and the [Marketing Lead](/agents/marketing/marketing-lead) sees it. # Motion URL: /business/nouns/motion · Id: `noun:motion` > A Motion is the shape of a sale: who buys an Offer and who acts for them, such as b2b, b2c, b2d, b2a, or b2a2b. A Motion is the shape of a sale: who buys an [Offer](/business/nouns/offer) and who acts for them, such as b2b, b2c, b2d, b2a, or b2a2b. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `code` | `string` | Yes | The code: b2b, b2c, b2d, b2a, b2h2a, b2a2b, b2a2c, or b2a2d. Each letter after the 2 names the next party in the chain. | | `buyer` | `string` | Yes | The party that accepts the Offer: a business, a consumer, a developer, or an Agent. | | `actor` | `string` | No | Who calls the Interfaces for the buyer: the buyer, a human operator, or an Agent. | ## Object ```json { "$id": "https://api.sb/quietcopy.com/motions/motion_1", "$type": "Motion", "code": "Example code", "buyer": "Example buyer", "actor": "Example actor" } ``` ## Relationships - A Motion **sells** many [Offers](/business/nouns/offer): each [Offer](/business/nouns/offer) sells through one Motion, which says who buys and who acts for them. `sells`, inverse [`soldIn`](/business/nouns/offer#rel-sold-in). - A Motion **is sold through by** many [Startup Templates](/business/nouns/startup-template): a [Startup Template](/business/nouns/startup-template) names the Motions its [Startups](/business/nouns/startup) sell through, such as b2b or b2a. `soldThroughBy`, inverse [`sellsThrough`](/business/nouns/startup-template#rel-sells-through). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Motion.get](/business/nouns/motion/get) | Returns one Motion by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Motion.list](/business/nouns/motion/list) | Returns Motions, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | A Motion is kept forever and never edited: it has no `update` or `delete`. ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Motion.get` | Yes | Yes | Yes | Yes | | `Motion.list` | Yes | Yes | Yes | Yes | ## Call it **Ask** ```text Show me the latest motion. ``` **API** ```bash curl https://api.sb/petpantry.shop/motions/motion_1 \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/petpantry.shop", "$type": "Motion", "$id": "https://api.sb/petpantry.shop/motions/motion_1", "motion": { "$id": "https://api.sb/petpantry.shop/motions/motion_1", "$type": "Motion", "code": "Example code", "buyer": "Example buyer" }, "links": { "self": "https://api.sb/petpantry.shop/motions/motion_1", "up": "https://api.sb/petpantry.shop/motions" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const motion = await $.Motion.get({ id: 'motion_1' }) ``` **CLI** ```bash npx startup-builder do Motion.get --json '{"id":"motion_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Motion.get({ id: 'motion_1' })" } } ``` ## Example An invoice API sells in b2d when a developer signs up and pays by card. It sells in b2a2b when an accounting firm is the [Customer](/business/nouns/customer) and its [Agent](/business/nouns/agent) calls the API at night. # Noun URL: /business/nouns/noun · Id: `noun:noun` > A Noun is a type of record, with its properties, its relationships, and the Verbs that act on it. A Noun is a type of record, with its properties, its relationships, and the [Verbs](/business/nouns/verb) that act on it. Each record is a [Thing](/business/nouns/thing) of exactly one Noun. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `name` | `string` | Yes | The singular, capitalized name. | | `properties` | `json` | No | Its properties, each with a name, a type, and whether it is required. | | `publishedIn` | [Version](/business/nouns/version) | No | The first published Version that serves it; from then on, edits go through a Change and `delete` refuses. | | `status` | `string` | Yes | One of `draft`, `published` or `retired`. | ## Object ```json { "$id": "https://api.sb/kilnbakery.com/nouns/noun_1", "$type": "Noun", "name": "Kiln Bakery", "properties": {}, "publishedIn": "version_1", "status": "draft" } ``` ## Relationships - A Noun **is acted on by** many [Verbs](/business/nouns/verb): every [Verb](/business/nouns/verb) acts on one Noun, which names it: `Startup.launch` acts on [Startup](/business/nouns/startup). `actedOnBy`, inverse [`actsOn`](/business/nouns/verb#rel-acts-on). - A Noun **is curated in** many [Datasets](/business/nouns/dataset): a [Dataset](/business/nouns/dataset) collects and vouches for the [Things](/business/nouns/thing) of exactly one Noun. `curatedIn`, inverse [`curates`](/business/nouns/dataset#rel-curates). - A Noun **is defined in** many [Systems](/business/nouns/system): the Nouns a [System](/business/nouns/system) keeps records of; several Systems can share one Noun. `definedIn`, inverse [`defines`](/business/nouns/system#rel-defines). - A Noun **is exposed by** one [Capability](/business/nouns/capability): a [Capability](/business/nouns/capability) exposes [Verbs](/business/nouns/verb) on one Noun family, metered, limited and logged under one key. `exposedBy`, inverse [`exposes`](/business/nouns/capability#rel-exposes). - A Noun’s **instances** are many [Things](/business/nouns/thing): a [Thing](/business/nouns/thing) takes the properties, relationships and [Verbs](/business/nouns/verb) of every Noun it is an instance of. `instances`, inverse [`instanceOf`](/business/nouns/thing#rel-instance-of). - A Noun **moves through** one [Lifecycle](/business/nouns/lifecycle): a Noun’s [Lifecycle](/business/nouns/lifecycle) lists the states its [Things](/business/nouns/thing) move through and the [Verbs](/business/nouns/verb) that move them. `movesThrough`, inverse [`governs`](/business/nouns/lifecycle#rel-governs). ## Lifecycle | State | Meaning | Moves to | | --- | --- | --- | | `draft` (first) | Defined and editable; no published Version serves it. | `published` on [`Version.deployed`](/business/events/Version.deployed) when the deployed Version is the first to include this Noun | | `published` | A published Version serves it; edits go through a Change, and `delete` refuses. | `retired` by [Noun.retire](/business/nouns/noun/retire) | | `retired` | New Versions leave it out; its records, its history and every pinned Version keep serving. | None: it ends here. | ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Noun.retire](/business/nouns/noun/retire) | Retire removes a published Noun from new Versions; its records, its history and every pinned Version keep serving. | [Product Lead](/agents/product/product-lead) | [`Noun.retired`](/business/events/Noun.retired) | One-way (customer): `send`, `do` | | [Noun.trace](/business/nouns/noun/trace) | Trace lists every Verb, Process, Offer, Dashboard and Version that references a Noun, so an edit or a retire shows its reach first. | [Worker](/business/nouns/worker) | [`Noun.traced`](/business/events/Noun.traced) | None. | | [Noun.create](/business/nouns/noun/create) | Creates a Noun. Inherited from [Noun](/business/nouns/noun). | None. | `Noun.created` | Two-way: `try`, `send`, `do` | | [Noun.get](/business/nouns/noun/get) | Returns one Noun by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Noun.list](/business/nouns/noun/list) | Returns Nouns, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Noun.update](/business/nouns/noun/update) | Changes the given properties of a Noun. Inherited from [Noun](/business/nouns/noun). | None. | `Noun.updated` | Two-way: `try`, `send`, `do` | | [Noun.delete](/business/nouns/noun/delete) | Deletes a Noun; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Noun.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Noun.create` | Yes | Yes | Yes | No | | `Noun.get` | Yes | Yes | Yes | Yes | | `Noun.list` | Yes | Yes | Yes | Yes | | `Noun.update` | Yes | Yes | Yes | No | | `Noun.delete` | Yes | Yes | Yes | No | | `Noun.retire` | Yes | No | No | No | | `Noun.trace` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Retire the latest noun. ``` **API** ```bash curl -X POST https://api.sb/shiftnote.app/nouns/noun_1/retire \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/shiftnote.app", "version": { "$id": "https://api.sb/shiftnote.app/versions/version_1", "$type": "Version", "fingerprint": "sha256:9f2c4e1a7b3d" }, "noun": { "$id": "https://api.sb/shiftnote.app/nouns/noun_1", "$type": "Noun", "name": "ShiftNote", "status": "retired" }, "action": { "$id": "https://api.sb/shiftnote.app/actions/action_1", "operation": "Noun.retire", "status": "done" }, "links": { "self": "https://api.sb/shiftnote.app/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { version, noun } = await $.Noun.retire({ noun: 'noun_1' }) ``` **CLI** ```bash npx startup-builder do Noun.retire --json '{"noun":"noun_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Noun.retire({ noun: 'noun_1' })" } } ``` ## Example [Offer](/business/nouns/offer) is a Noun. Every Offer record has a `price` and `terms`, includes one [Product](/business/nouns/product), and moves only through Verbs such as [`Offer.publish`](/business/nouns/offer/publish) and [`Offer.accept`](/business/nouns/offer/accept). # retire URL: /business/nouns/noun/retire · Id: `verb:Noun.retire` · Call: `await $.Noun.retire({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Retire removes a published Noun from new Versions; its records, its history and every pinned Version keep serving. Retire removes a published [Noun](/business/nouns/noun) from new [Versions](/business/nouns/version); its records, its history and every pinned Version keep serving. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `noun` | [Noun](/business/nouns/noun) | Yes | The Noun to retire. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `version` | [Version](/business/nouns/version) | Yes | The new Version, without the Noun. | | `noun` | [Noun](/business/nouns/noun) | Yes | The Noun, now retired from new Versions. | ## Effects - Emits [`Noun.retired`](/business/events/Noun.retired). - Performed by the [Product Lead](/agents/product/product-lead). - One-way (customer): it waits out its delay window, and runs in the `send` and `do` modes. - Opens a new Version without the Noun through a Change. - Keeps every Version a Customer pins serving it. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Noun.retire](/business/nouns/noun/retire) | ## When it waits | Gate | Default | | --- | --- | | Decision class | High: one-way, broad (customer) | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | 1 business day, in which a watcher can pause, redirect or cancel it; then it runs. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Retire the latest noun. ``` **API** ```bash curl -X POST https://api.sb/shiftnote.app/nouns/noun_1/retire \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/shiftnote.app", "version": { "$id": "https://api.sb/shiftnote.app/versions/version_1", "$type": "Version", "fingerprint": "sha256:9f2c4e1a7b3d" }, "noun": { "$id": "https://api.sb/shiftnote.app/nouns/noun_1", "$type": "Noun", "name": "ShiftNote", "status": "retired" }, "action": { "$id": "https://api.sb/shiftnote.app/actions/action_1", "operation": "Noun.retire", "status": "done" }, "links": { "self": "https://api.sb/shiftnote.app/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { version, noun } = await $.Noun.retire({ noun: 'noun_1' }) ``` **CLI** ```bash npx startup-builder do Noun.retire --json '{"noun":"noun_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Noun.retire({ noun: 'noun_1' })" } } ``` # trace URL: /business/nouns/noun/trace · Id: `verb:Noun.trace` · Call: `await $.Noun.trace({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Trace lists every Verb, Process, Offer, Dashboard and Version that references a Noun, so an edit or a retire shows its reach first. Trace lists every [Verb](/business/nouns/verb), [Process](/business/nouns/process), [Offer](/business/nouns/offer), [Dashboard](/business/nouns/dashboard) and [Version](/business/nouns/version) that references a [Noun](/business/nouns/noun), so an edit or a retire shows its reach first. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `noun` | [Noun](/business/nouns/noun) | Yes | The Noun to trace. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `uses` | `json` | Yes | Each referencing entry, by kind and id, with the published Versions that serve it. | | `noun` | [Noun](/business/nouns/noun) | Yes | The Noun traced. | ## Effects - Emits [`Noun.traced`](/business/events/Noun.traced). ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Noun.trace](/business/nouns/noun/trace) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Trace the latest noun. ``` **API** ```bash curl -X POST https://api.sb/shiftnote.app/nouns/noun_1/trace \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/shiftnote.app", "uses": {}, "noun": { "$id": "https://api.sb/shiftnote.app/nouns/noun_1", "$type": "Noun", "name": "ShiftNote", "status": "draft" }, "action": { "$id": "https://api.sb/shiftnote.app/actions/action_1", "operation": "Noun.trace", "status": "done" }, "links": { "self": "https://api.sb/shiftnote.app/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { uses, noun } = await $.Noun.trace({ noun: 'noun_1' }) ``` **CLI** ```bash npx startup-builder do Noun.trace --json '{"noun":"noun_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Noun.trace({ noun: 'noun_1' })" } } ``` # accept URL: /business/nouns/offer/accept · Id: `verb:Offer.accept` · Call: `await $.Offer.accept({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Accept records that a party takes an Offer, which makes that party a Customer of the Startup. Accept records that a party takes an [Offer](/business/nouns/offer), which makes that party a [Customer](/business/nouns/customer) of the [Startup](/business/nouns/startup). ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `offer` | [Offer](/business/nouns/offer) | Yes | The Offer to accept. | | `party` | `string` | Yes | The person or organization accepting. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `customer` | [Customer](/business/nouns/customer) | Yes | The Customer the party is or becomes. | | `offer` | [Offer](/business/nouns/offer) | Yes | The Offer accepted. | ## Effects - Emits [`Offer.accepted`](/business/events/Offer.accepted). - Creates a Customer when the party has none at this Startup. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The operation is part of an Offer the caller has not accepted or paid for. | [`payment-required`](/code/api/errors/payment-required) | Accept the Offer named in the response, then retry the call. | [Offer.accept](/business/nouns/offer/accept) | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Offer.accept](/business/nouns/offer/accept) | | The record is not in a state that allows this Verb, so the call is refused. | [`refused`](/code/api/errors/refused) | Read the record, run the Verb that moves it to an allowed state, then retry. | [Offer.accept](/business/nouns/offer/accept) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example A developer accepts a $0 Offer for an API key and becomes a Customer of the Startup that made it. **Ask** ```text Accept the offer “Grain-free kibble, 12 lb”. ``` **API** ```bash curl -X POST https://api.sb/petpantry.shop/offers/offer_1/accept \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"party":"Lena Fischer"}' ``` ```json { "api": "https://api.sb/petpantry.shop", "customer": { "$id": "https://api.sb/petpantry.shop/customers/customer_1", "$type": "Customer", "since": "2026-10-22T12:00:00Z" }, "offer": { "$id": "https://api.sb/petpantry.shop/offers/offer_1", "$type": "Offer", "price": { "amount": 54, "currency": "USD" } }, "action": { "$id": "https://api.sb/petpantry.shop/actions/action_1", "operation": "Offer.accept", "status": "done" }, "links": { "self": "https://api.sb/petpantry.shop/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { customer, offer } = await $.Offer.accept({ offer: 'offer_1', party: 'Lena Fischer' }) ``` **CLI** ```bash npx startup-builder do Offer.accept --json '{"offer":"offer_1","party":"Lena Fischer"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Offer.accept({ offer: 'offer_1', party: 'Lena Fischer' })" } } ``` # grant URL: /business/nouns/offer/grant · Id: `verb:Offer.grant` · Call: `await $.Offer.grant({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Grant adds an Entitlement to an Offer: a Verb its Customers may call, optionally bounded by a Limit. Grant adds an [Entitlement](/business/nouns/entitlement) to an [Offer](/business/nouns/offer): a [Verb](/business/nouns/verb) its [Customers](/business/nouns/customer) may call, optionally bounded by a [Limit](/business/nouns/limit). ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `offer` | [Offer](/business/nouns/offer) | Yes | The Offer that grants it. | | `verb` | [Verb](/business/nouns/verb) | Yes | The Verb its Customers may call, as `Noun.verb`. | | `limit` | [Limit](/business/nouns/limit) | No | The Limit that bounds it. Unset: a feature, called as often as the Customer likes. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `entitlement` | [Entitlement](/business/nouns/entitlement) | Yes | The new Entitlement, granted by the Offer. | | `offer` | [Offer](/business/nouns/offer) | Yes | The Offer, with the Entitlement added. | ## Effects - Emits [`Offer.granted`](/business/events/Offer.granted). - Performed by the [Product Lead](/agents/product/product-lead). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Every Customer holding the Offer holds the Entitlement on their next call; no Subscription changes. - Adds the Verb to the Offer’s row in the pricing table and the Portal’s plan comparison. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Offer.grant](/business/nouns/offer/grant) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Grant the offer “Saturday sourdough” with a verb. ``` **API** ```bash curl -X POST https://api.sb/kilnbakery.com/offers/offer_1/grant \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"verb":"verb_1"}' ``` ```json { "api": "https://api.sb/kilnbakery.com", "entitlement": { "$id": "https://api.sb/kilnbakery.com/entitlements/entitlement_1", "$type": "Entitlement", "verb": "verb_1" }, "offer": { "$id": "https://api.sb/kilnbakery.com/offers/offer_1", "$type": "Offer", "price": { "amount": 9, "currency": "USD" } }, "action": { "$id": "https://api.sb/kilnbakery.com/actions/action_1", "operation": "Offer.grant", "status": "done" }, "links": { "self": "https://api.sb/kilnbakery.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { entitlement, offer } = await $.Offer.grant({ offer: 'offer_1', verb: 'verb_1' }) ``` **CLI** ```bash npx startup-builder do Offer.grant --json '{"offer":"offer_1","verb":"verb_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Offer.grant({ offer: 'offer_1', verb: 'verb_1' })" } } ``` Next: [`Offer.update`](/business/nouns/offer/update) (in `guide:cap-usage-on-a-plan`). Guides that call it: [Lock a feature to a plan](/products/offers/lock-a-feature-to-a-plan), [Cap usage on a plan](/products/offers/cap-usage-on-a-plan). # Offer URL: /business/nouns/offer · Id: `noun:offer` > An Offer is a Product, under a Brand, at a price, on terms, made by a Startup. An Offer is a [Product](/business/nouns/product), under a [Brand](/business/nouns/brand), at a [Price](/business/nouns/price), on terms, made by a [Startup](/business/nouns/startup). One Product sells as many Offers, and a [Customer](/business/nouns/customer) accepts an Offer, never a Product. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `price` | `money` | Yes | The amount, currency, and unit. Zero is a price. Never randomized. | | `terms` | `text` | No | The conditions the Customer accepts, refund rights included. Never randomized. | | `from` | `string` | No | Lineage: the slot it compiles from, as `Hypothesis#@v`. | | `activation` | `json` | No | The Event, count and window that mark a Customer activated, such as `Reminder.sent` 20 times within 7 days. | | `credit` | `money` | No | The Credit Grant each purchase issues, for an Offer that sells prepaid credit, such as $50 of calls. | | `atBound` | `string` | No | What a call past an Entitlement’s Limit gets: `stop`, `overage` or `upgrade` (refuse it, bill it through the Meter, or move to the next Offer). | | `interval` | `string` | No | How often it bills: `once`, `day`, `week`, `month` or `year`. | | `availableFrom` | `datetime` | No | When it can first be bought. Unset: from when it is published. | | `availableUntil` | `datetime` | No | When it can last be bought. Existing Subscriptions continue past it. | | `trial` | `json` | No | The free trial every new Customer starts with: `days`, and `card` true to take a card up front. Unset: no trial. | | `seats` | `string` | No | How a per-seat Price counts: `manual` (the buyer sets the quantity) or `members` (people in the Customer’s Tenant, prorated as they change). | | `uptime` | `json` | No | The monthly uptime it promises, and the share of that month’s charge credited back below each level. | | `license` | `string` | No | What a buyer may do with the records it sells: use them `internal`ly, `display` them to its own users, or `redistribute` them. | | `attribution` | `text` | No | The credit line a buyer shows wherever the records appear. | | `privateTo` | [Party](/business/nouns/party) | No | The one Party who sees it and may accept it, making it a private Offer; no pricing page lists it. | ## Object ```json { "$id": "https://api.sb/petpantry.shop/offers/offer_1", "$type": "Offer", "price": { "amount": 54, "currency": "USD" }, "terms": "Full refund within 14 days of purchase. Delivery in 2 business days.", "from": "Hypothesis#approach@v1", "activation": {}, "credit": { "amount": 54, "currency": "USD" }, "atBound": "stop", "interval": "once", "availableFrom": "2026-10-22T12:00:00Z", "availableUntil": "2026-10-22T12:00:00Z", "trial": { "days": 14, "card": true }, "seats": "manual", "uptime": { "target": 99.9, "credits": [ { "below": 99.9, "percent": 10 }, { "below": 99, "percent": 25 } ] }, "license": "internal", "attribution": "Renewal data from Leaseline", "privateTo": "party_1" } ``` ## Anatomy RouteWise (`routewise.dev`), a sample business, sells three Offers: | Offer | Price | Features | Limits | At its bound | On sale | | --- | --- | --- | --- | --- | --- | | Starter (`starter`) | $49 a month | [Dashboard.ask](/business/nouns/dashboard/ask) | [Collection.query](/business/nouns/collection/query): 10,000 a calendar month | `upgrade` to Fleet | Always | | Fleet (`fleet`) | $199 a month | [Collection.export](/business/nouns/collection/export), [Dashboard.ask](/business/nouns/dashboard/ask) | [Collection.query](/business/nouns/collection/query): 100,000 a calendar month | `overage` | Always | | Route audit (`route-audit`) | $499 once | None. | [Document.render](/business/nouns/document/render): 1 in all; [Order.revise](/business/nouns/order/revise): 2 in all | `stop` | 2026-11-01 to 2027-01-31 | An Entitlement bounded by a Limit has `kind` `limit`; one without has `kind` `feature`. The `kind` is computed, never set. | `atBound` | A call past the Limit | | --- | --- | | `stop` | Refused: the Verb replies 402 `payment-required`. | | `overage` | Allowed: each unit past the Limit is billed through the Meter. | | `upgrade` | Refused with 402 `payment-required`, naming the next Offer, which `Entitlement.check` returns as `upgrade`. | [Offer.publish](/business/nouns/offer/publish) puts each Offer on every buy surface: `checkout`, `paymentLink`, `pricingTable`, `portalEntry`, `mcpBuyTool`, `http402`. ## Relationships - An Offer **is accepted by** many [Customers](/business/nouns/customer): a party becomes a [Customer](/business/nouns/customer) by accepting any Offer, at any price including zero. `acceptedBy`, inverse [`accepts`](/business/nouns/customer#rel-accepts). - An Offer **is branded by** one [Brand](/business/nouns/brand): each Offer carries exactly one [Brand](/business/nouns/brand), whose name, voice and logo the buyer sees. `brandedBy`, inverse [`brands`](/business/nouns/brand#rel-brands). - An Offer **has** many [Coupons](/business/nouns/coupon): a [Coupon](/business/nouns/coupon) applies only to the Offers it names; an Offer may accept several Coupons. `coupons`, inverse [`discounts`](/business/nouns/coupon#rel-discounts). - An Offer **has** many [Funnels](/business/nouns/funnel): each [Funnel](/business/nouns/funnel)’s path ends at one Offer, after its landing [Page](/business/nouns/page), opt-in and [Sequence](/business/nouns/sequence). `funnels`, inverse [`leadsTo`](/business/nouns/funnel#rel-leads-to). - An Offer **is governed by** one [Outcome Contract](/business/nouns/outcome-contract): an [Outcome Contract](/business/nouns/outcome-contract) warrants the result an Offer sells: its done state, acceptance, assurance and remedy. `governedBy`, inverse [`governs`](/business/nouns/outcome-contract#rel-governs). - An Offer **grants** many [Entitlements](/business/nouns/entitlement): an accepted Offer grants [Entitlements](/business/nouns/entitlement), each a [Verb](/business/nouns/verb) on a [Noun](/business/nouns/noun), optionally bounded by a [Limit](/business/nouns/limit). `grants`, inverse [`grantedBy`](/business/nouns/entitlement#rel-granted-by). - An Offer **includes** one [Product](/business/nouns/product): each Offer sells one [Product](/business/nouns/product); one Product sits inside many Offers at different prices and terms. `includes`, inverse [`includedIn`](/business/nouns/product#rel-included-in). - An Offer **is offered by** one [Startup](/business/nouns/startup): each Offer has one maker, which earns its revenue and answers for its terms. `offeredBy`, inverse [`offers`](/business/nouns/startup#rel-offers). - An Offer **is ordered in** many [Orders](/business/nouns/order): an [Order](/business/nouns/order) commits to buying one or more Offers once. `orderedIn`, inverse [`buys`](/business/nouns/order#rel-buys). - An Offer **is priced at** one [Price](/business/nouns/price): every Offer embeds one [Price](/business/nouns/price): amount, currency, unit and tiers; zero is a Price. `pricedAt`, inverse [`priceOf`](/business/nouns/price#rel-price-of). - An Offer **is promoted by** many [Ads](/business/nouns/ad): each [Ad](/business/nouns/ad) sells one Offer. `promotedBy`, inverse [`promotes`](/business/nouns/ad#rel-promotes). - An Offer **is pursued in** many [Deals](/business/nouns/deal): a [Deal](/business/nouns/deal) asks one buyer to accept one or more Offers. `pursuedIn`, inverse [`pursues`](/business/nouns/deal#rel-pursues). - An Offer **is quoted in** many [Quotes](/business/nouns/quote): a [Quote](/business/nouns/quote) prices one or more Offers for one buyer. `quotedIn`, inverse [`proposes`](/business/nouns/quote#rel-proposes). - An Offer **has** many [Reviews](/business/nouns/review): a [Review](/business/nouns/review) evaluates one Offer; Reviews of a [Product](/business/nouns/product) or [Brand](/business/nouns/brand) roll up through its Offers. `reviews`, inverse [`evaluates`](/business/nouns/review#rel-evaluates). - An Offer **is sold in** one [Motion](/business/nouns/motion): each Offer sells through one [Motion](/business/nouns/motion), which says who buys and who acts for them. `soldIn`, inverse [`sells`](/business/nouns/motion#rel-sells). - An Offer **has** many [Subscriptions](/business/nouns/subscription): a [Subscription](/business/nouns/subscription) bills one recurring Offer each [Period](/business/nouns/period) until canceled. `subscriptions`, inverse [`renews`](/business/nouns/subscription#rel-renews). - An Offer **targets** many [Personas](/business/nouns/persona): an Offer speaks to and is priced for named [Personas](/business/nouns/persona). `targets`, inverse [`targetedBy`](/business/nouns/persona#rel-targeted-by). - An Offer **has** one [Waitlist](/business/nouns/waitlist): a [Waitlist](/business/nouns/waitlist) admits its [Leads](/business/nouns/lead) to one Offer once that Offer opens. `waitlist`, inverse [`awaits`](/business/nouns/waitlist#rel-awaits). ## Lifecycle | State | Meaning | Moves to | | --- | --- | --- | | `draft` (first) | The Offer is being written: no party can see or accept it. | `published` by [Offer.publish](/business/nouns/offer/publish) | | `published` | Parties can see the Offer, accept it and subscribe to it. | `withdrawn` by [Offer.withdraw](/business/nouns/offer/withdraw) | | `withdrawn` | The Offer takes no new Customers; every Order and Subscription it made stays in force. | None: it ends here. | ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Offer.accept](/business/nouns/offer/accept) | Accept records that a party takes an Offer, which makes that party a Customer of the Startup. | [Customer](/business/nouns/customer) | [`Offer.accepted`](/business/events/Offer.accepted) | None. | | [Offer.grant](/business/nouns/offer/grant) | Grant adds an Entitlement to an Offer: a Verb its Customers may call, optionally bounded by a Limit. | [Product Lead](/agents/product/product-lead) | [`Offer.granted`](/business/events/Offer.granted) | Two-way: `try`, `send`, `do` | | [Offer.publish](/business/nouns/offer/publish) | Publish makes an Offer available for parties to accept. | [Product Lead](/agents/product/product-lead) | [`Offer.published`](/business/events/Offer.published) | None. | | [Offer.subscribe](/business/nouns/offer/subscribe) | Subscribe accepts a recurring Offer as a Subscription that renews each period until it ends. | [Billing Specialist](/agents/finance/billing-specialist) | [`Offer.subscribed`](/business/events/Offer.subscribed) | None. | | [Offer.trial](/business/nouns/offer/trial) | Trial starts a Customer on an Offer free for a set number of days, with or without a card, converting or ending by its terms. | [Billing Specialist](/agents/finance/billing-specialist) | [`Offer.trialed`](/business/events/Offer.trialed) | Two-way: `try`, `send`, `do` | | [Offer.withdraw](/business/nouns/offer/withdraw) | Withdraw closes a published Offer to new Customers and leaves every existing Order and Subscription in force. | [Product Lead](/agents/product/product-lead) | [`Offer.withdrawn`](/business/events/Offer.withdrawn) | None. | | [Offer.create](/business/nouns/offer/create) | Creates an Offer. Inherited from [Noun](/business/nouns/noun). | None. | `Offer.created` | Two-way: `try`, `send`, `do` | | [Offer.get](/business/nouns/offer/get) | Returns one Offer by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Offer.list](/business/nouns/offer/list) | Returns Offers, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Offer.update](/business/nouns/offer/update) | Changes the given properties of an Offer. Inherited from [Noun](/business/nouns/noun). | None. | `Offer.updated` | Two-way: `try`, `send`, `do` | | [Offer.delete](/business/nouns/offer/delete) | Deletes an Offer; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Offer.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Offer.create` | Yes | Yes | Yes | No | | `Offer.get` | Yes | Yes | Yes | Yes | | `Offer.list` | Yes | Yes | Yes | Yes | | `Offer.update` | Yes | Yes | Yes | No | | `Offer.delete` | Yes | Yes | Yes | No | | `Offer.accept` | Yes | Yes | Yes | No | | `Offer.grant` | Yes | Yes | Yes | No | | `Offer.publish` | Yes | Yes | Yes | No | | `Offer.subscribe` | Yes | Yes | Yes | No | | `Offer.trial` | Yes | Yes | Yes | No | | `Offer.withdraw` | Yes | Yes | Yes | No | ## Stripe **Product** (`product`). The source of truth is db.sb, and Stripe holds a copy written from it. | Property | Stripe field | Source of truth | | --- | --- | --- | | `price` | `default_price` | db.sb | ## Call it **Ask** ```text Publish the offer “RouteWise API”. ``` **API** ```bash curl -X POST https://api.sb/routewise.dev/offers/offer_1/publish \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/routewise.dev", "offer": { "$id": "https://api.sb/routewise.dev/offers/offer_1", "$type": "Offer", "price": { "amount": 25, "currency": "USD" } }, "action": { "$id": "https://api.sb/routewise.dev/actions/action_1", "operation": "Offer.publish", "status": "done" }, "links": { "self": "https://api.sb/routewise.dev/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const offer = await $.Offer.publish({ offer: 'offer_1' }) ``` **CLI** ```bash npx startup-builder do Offer.publish --json '{"offer":"offer_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Offer.publish({ offer: 'offer_1' })" } } ``` ## Example A dental bookkeeping Startup sells one Product as two Offers: $600 a month for monthly closes, or $2,400 once for catch-up books. Both carry its one Brand. # publish URL: /business/nouns/offer/publish · Id: `verb:Offer.publish` · Call: `await $.Offer.publish({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Publish makes an Offer available for parties to accept. Publish makes an [Offer](/business/nouns/offer) available for parties to accept. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `offer` | [Offer](/business/nouns/offer) | Yes | The Offer to publish. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `offer` | [Offer](/business/nouns/offer) | Yes | The Offer, now open to accept. | ## Effects - Emits [`Offer.published`](/business/events/Offer.published). - Performed by the [Product Lead](/agents/product/product-lead). ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Offer.publish](/business/nouns/offer/publish) | | The record is not in a state that allows this Verb, so the call is refused. | [`refused`](/code/api/errors/refused) | Read the record, run the Verb that moves it to an allowed state, then retry. | [Offer.publish](/business/nouns/offer/publish) | | The median Customer’s Cost leaves less than the Startup’s target margin at this Price. | [`below-contribution-floor`](/code/api/errors/below-contribution-floor) | Raise the Price to the floor the error names, or grant fewer Entitlements. | [Offer.update](/business/nouns/offer/update) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Medium: two-way, visible | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | 1 business hour, in which a watcher can pause, redirect or cancel it; then it runs. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example An [Agent](/business/nouns/agent) publishes a $0 Offer for an API key, and any party can accept it from then on. **Ask** ```text Publish the offer “RouteWise API”. ``` **API** ```bash curl -X POST https://api.sb/routewise.dev/offers/offer_1/publish \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/routewise.dev", "offer": { "$id": "https://api.sb/routewise.dev/offers/offer_1", "$type": "Offer", "price": { "amount": 25, "currency": "USD" } }, "action": { "$id": "https://api.sb/routewise.dev/actions/action_1", "operation": "Offer.publish", "status": "done" }, "links": { "self": "https://api.sb/routewise.dev/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const offer = await $.Offer.publish({ offer: 'offer_1' }) ``` **CLI** ```bash npx startup-builder do Offer.publish --json '{"offer":"offer_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Offer.publish({ offer: 'offer_1' })" } } ``` Next: [`Survey.create`](/business/nouns/survey/create) (in `guide:find-out-if-anyone-wants-this`), [`Offer.withdraw`](/business/nouns/offer/withdraw) (in `guide:raise-my-price`). Guides that call it: [Take a payment](/systems/finance/take-a-payment), [Charge monthly](/systems/finance/charge-monthly), [Ship an API](/products/api/ship-an-api), [Find out if anyone wants this](/start/guides/find-out-if-anyone-wants-this), [Charge per use](/start/guides/charge-per-use) and 7 more. # subscribe URL: /business/nouns/offer/subscribe · Id: `verb:Offer.subscribe` · Call: `await $.Offer.subscribe({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Subscribe accepts a recurring Offer as a Subscription that renews each period until it ends. Subscribe accepts a recurring [Offer](/business/nouns/offer) as a [Subscription](/business/nouns/subscription) that renews each period until it ends. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `offer` | [Offer](/business/nouns/offer) | Yes | The recurring Offer. | | `quantity` | `integer` | No | Seats or units. Defaults to 1. | | `promotionCode` | `string` | No | A promotion code the buyer typed; applies its Coupon for the Coupon’s duration. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `subscription` | [Subscription](/business/nouns/subscription) | Yes | The new Subscription. | | `offer` | [Offer](/business/nouns/offer) | Yes | The Offer subscribed to. | ## Effects - Emits [`Offer.subscribed`](/business/events/Offer.subscribed). - Performed by the [Billing Specialist](/agents/finance/billing-specialist). - Makes the party a Customer when it is not one yet. - Grants the Entitlements the Offer includes. - Bills the first period. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The input does not match the schema of the operation. | [`invalid-input`](/code/api/errors/invalid-input) | Read the schema of the operation, then send every required field with the right type. | [Offer.subscribe](/business/nouns/offer/subscribe) | | The operation is part of an Offer the caller has not accepted or paid for. | [`payment-required`](/code/api/errors/payment-required) | Accept the Offer named in the response, then retry the call. | [Offer.accept](/business/nouns/offer/accept) | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Offer.subscribe](/business/nouns/offer/subscribe) | | The record is not in a state that allows this Verb, so the call is refused. | [`refused`](/code/api/errors/refused) | Read the record, run the Verb that moves it to an allowed state, then retry. | [Offer.subscribe](/business/nouns/offer/subscribe) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Subscribe a customer to the offer “Résumé review”. ``` **API** ```bash curl -X POST https://api.sb/quietcopy.com/offers/offer_1/subscribe \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/quietcopy.com", "subscription": { "$id": "https://api.sb/quietcopy.com/subscriptions/subscription_1", "$type": "Subscription", "status": "active" }, "offer": { "$id": "https://api.sb/quietcopy.com/offers/offer_1", "$type": "Offer", "price": { "amount": 39, "currency": "USD" } }, "action": { "$id": "https://api.sb/quietcopy.com/actions/action_1", "operation": "Offer.subscribe", "status": "done" }, "links": { "self": "https://api.sb/quietcopy.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { subscription, offer } = await $.Offer.subscribe({ offer: 'offer_1' }) ``` **CLI** ```bash npx startup-builder do Offer.subscribe --json '{"offer":"offer_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Offer.subscribe({ offer: 'offer_1' })" } } ``` Next: [`Role.staff`](/business/nouns/role/staff) (in `guide:buy-a-specialist-agent-for-a-seat`). Guides that call it: [Buy a specialist agent for a seat](/agents/buy-a-specialist-agent-for-a-seat). # trial URL: /business/nouns/offer/trial · Id: `verb:Offer.trial` · Call: `await $.Offer.trial({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Trial starts a Customer on an Offer free for a set number of days, with or without a card, converting or ending by its terms. Trial starts a [Customer](/business/nouns/customer) on an [Offer](/business/nouns/offer) free for a set number of days, with or without a card, converting or ending by its terms. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `offer` | [Offer](/business/nouns/offer) | Yes | The Offer to try. | | `customer` | [Customer](/business/nouns/customer) | Yes | The Customer who tries it. | | `days` | `integer` | Yes | How long the trial runs. Never randomized. | | `card` | `boolean` | No | True to take a card up front and charge it when the trial ends. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `subscription` | [Subscription](/business/nouns/subscription) | Yes | The Subscription, free until the trial ends. | | `offer` | [Offer](/business/nouns/offer) | Yes | The Offer the trial is on. | ## Effects - Emits [`Offer.trialed`](/business/events/Offer.trialed). - Performed by the [Billing Specialist](/agents/finance/billing-specialist). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - With a card on file, converts to a paid Subscription at the end unless canceled first. - Without a card, ends at the end and opens a conversion Task for the Success Manager. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Offer.trial](/business/nouns/offer/trial) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Trial the offer “Résumé review” with a customer. ``` **API** ```bash curl -X POST https://api.sb/quietcopy.com/offers/offer_1/trial \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"customer":"customer_1","days":1}' ``` ```json { "api": "https://api.sb/quietcopy.com", "subscription": { "$id": "https://api.sb/quietcopy.com/subscriptions/subscription_1", "$type": "Subscription", "status": "active" }, "offer": { "$id": "https://api.sb/quietcopy.com/offers/offer_1", "$type": "Offer", "price": { "amount": 39, "currency": "USD" } }, "action": { "$id": "https://api.sb/quietcopy.com/actions/action_1", "operation": "Offer.trial", "status": "done" }, "links": { "self": "https://api.sb/quietcopy.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { subscription, offer } = await $.Offer.trial({ offer: 'offer_1', customer: 'customer_1', days: 1 }) ``` **CLI** ```bash npx startup-builder do Offer.trial --json '{"offer":"offer_1","customer":"customer_1","days":1}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Offer.trial({ offer: 'offer_1', customer: 'customer_1', days: 1 })" } } ``` Guides that call it: [Give a customer a free trial](/products/offers/give-a-free-trial). # withdraw URL: /business/nouns/offer/withdraw · Id: `verb:Offer.withdraw` · Call: `await $.Offer.withdraw({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Withdraw closes a published Offer to new Customers and leaves every existing Order and Subscription in force. Withdraw closes a published [Offer](/business/nouns/offer) to new [Customers](/business/nouns/customer) and leaves every existing [Order](/business/nouns/order) and [Subscription](/business/nouns/subscription) in force. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `offer` | [Offer](/business/nouns/offer) | Yes | The Offer to withdraw. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `offer` | [Offer](/business/nouns/offer) | Yes | The Offer, closed to new acceptance. | ## Effects - Emits [`Offer.withdrawn`](/business/events/Offer.withdrawn). - Performed by the [Product Lead](/agents/product/product-lead). ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Offer.withdraw](/business/nouns/offer/withdraw) | | The record is not in a state that allows this Verb, so the call is refused. | [`refused`](/code/api/errors/refused) | Read the record, run the Verb that moves it to an allowed state, then retry. | [Offer.withdraw](/business/nouns/offer/withdraw) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Medium: two-way, visible | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | 1 business hour, in which a watcher can pause, redirect or cancel it; then it runs. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Withdraw the offer “Algebra session”. ``` **API** ```bash curl -X POST https://api.sb/tutorloop.com/offers/offer_1/withdraw \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/tutorloop.com", "offer": { "$id": "https://api.sb/tutorloop.com/offers/offer_1", "$type": "Offer", "price": { "amount": 60, "currency": "USD" } }, "action": { "$id": "https://api.sb/tutorloop.com/actions/action_1", "operation": "Offer.withdraw", "status": "done" }, "links": { "self": "https://api.sb/tutorloop.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const offer = await $.Offer.withdraw({ offer: 'offer_1' }) ``` **CLI** ```bash npx startup-builder do Offer.withdraw --json '{"offer":"offer_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Offer.withdraw({ offer: 'offer_1' })" } } ``` Guides that call it: [Raise my price](/products/offers/raise-my-price). # Opening URL: /business/nouns/opening · Id: `noun:opening` > An Opening is a Startup’s computed need for a Human in a Role: its kind, its reason, and the Hypothesis a hire must prove. An Opening is a [Startup](/business/nouns/startup)’s computed need for a [Human](/business/nouns/human) in a [Role](/business/nouns/role): its kind, its reason, and the [Hypothesis](/business/nouns/hypothesis) a hire must prove. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `role` | [Role](/business/nouns/role) | Yes | The Role the Human joins, by taking a share of it. | | `kind` | `string` | Yes | One of `floor`, `contractor`, `employee`, or `cofounder`. | | `reason` | `string` | Yes | One of `floor`, `credential`, `edge`, `relationship`, `capital`, `capacity`, or `distribution`. | | `hypothesis` | [Hypothesis](/business/nouns/hypothesis) | Yes | The result a hire must beat the incumbent Agent on. | | `skills` | list of [Skill](/business/nouns/skill) | No | The Skills required, each citing the Evidence that shows the gap. | | `credentials` | list of [Credential](/business/nouns/credential) | No | The Credentials a Reserved Act in the Role requires. | | `commitment` | `string` | No | Hours per week, from a few hours to full time. | | `terms` | `url` | No | The published terms for this kind of Opening. | | `listed` | `boolean` | No | True once the Opening is public; unlisted Openings reach only the talent pool. | ## Object ```json { "$id": "https://api.sb/quietcopy.com/openings/opening_1", "$type": "Opening", "role": "role_1", "kind": "floor", "reason": "floor", "hypothesis": "hypothesis_1", "skills": [ "skill_1" ], "credentials": [ "credential_1" ], "commitment": "Example commitment", "terms": "https://quietcopy.com", "listed": true } ``` ## Relationships - An Opening **has** many [Candidates](/business/nouns/candidate): [Candidates](/business/nouns/candidate) for an Opening are screened only on what its [Hypothesis](/business/nouns/hypothesis) still lacks. `candidates`, inverse [`appliesTo`](/business/nouns/candidate#rel-applies-to). - An Opening **staffs** one [Role](/business/nouns/role): an Opening is a need for a [Human](/business/nouns/human) in one [Role](/business/nouns/role), taking a share of that Role’s work. `staffs`, inverse [`openings`](/business/nouns/role#rel-openings). - An Opening **tests** one [Hypothesis](/business/nouns/hypothesis): a hire into an Opening must prove its [Hypothesis](/business/nouns/hypothesis). `tests`, inverse [`testedByOpening`](/business/nouns/hypothesis#rel-tested-by-opening). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Opening.create](/business/nouns/opening/create) | Creates an Opening. Inherited from [Noun](/business/nouns/noun). | None. | `Opening.created` | Two-way: `try`, `send`, `do` | | [Opening.get](/business/nouns/opening/get) | Returns one Opening by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Opening.list](/business/nouns/opening/list) | Returns Openings, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Opening.update](/business/nouns/opening/update) | Changes the given properties of an Opening. Inherited from [Noun](/business/nouns/noun). | None. | `Opening.updated` | Two-way: `try`, `send`, `do` | | [Opening.delete](/business/nouns/opening/delete) | Deletes an Opening; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Opening.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Opening.create` | Yes | Yes | Yes | No | | `Opening.get` | Yes | Yes | Yes | Yes | | `Opening.list` | Yes | Yes | Yes | Yes | | `Opening.update` | Yes | Yes | Yes | No | | `Opening.delete` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Add an opening to TutorLoop with a role and a hypothesis. ``` **API** ```bash curl -X POST https://api.sb/tutorloop.com/openings \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"role":"role_1","kind":"floor","reason":"floor","hypothesis":"hypothesis_1"}' ``` ```json { "api": "https://api.sb/tutorloop.com", "opening": { "$id": "https://api.sb/tutorloop.com/openings/opening_1", "$type": "Opening", "role": "role_1", "kind": "floor", "reason": "floor", "hypothesis": "hypothesis_1" }, "action": { "$id": "https://api.sb/tutorloop.com/actions/action_1", "operation": "Opening.create", "status": "done" }, "links": { "self": "https://api.sb/tutorloop.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const opening = await $.Opening.create({ role: 'role_1', kind: 'floor', reason: 'floor', hypothesis: 'hypothesis_1' }) ``` **CLI** ```bash npx startup-builder do Opening.create --json '{"role":"role_1","kind":"floor","reason":"floor","hypothesis":"hypothesis_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Opening.create({ role: 'role_1', kind: 'floor', reason: 'floor', hypothesis: 'hypothesis_1' })" } } ``` ## Example A visa-petition Startup opens a `floor` Opening with reason `credential` in its [Legal Lead](/agents/legal/legal-lead) Role. It asks for a licensed attorney, four hours a week, to file what its [Agents](/business/nouns/agent) draft. It stays unlisted until the talent pool comes up empty. # cancel URL: /business/nouns/order/cancel · Id: `verb:Order.cancel` · Call: `await $.Order.cancel({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Cancel ends an Order before fulfillment and returns any payment in full. Cancel ends an [Order](/business/nouns/order) before fulfillment and returns any payment in full. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `order` | [Order](/business/nouns/order) | Yes | The unfulfilled Order. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `order` | [Order](/business/nouns/order) | Yes | The canceled Order. | ## Effects - Emits [`Order.canceled`](/business/events/Order.canceled). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Posts the reversing Entries for any payment. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Order.cancel](/business/nouns/order/cancel) | | The record changed since it was read, so the write would overwrite a newer version. | [`conflict`](/code/api/errors/conflict) | Read the record again, then retry the write against its current state. | [Order.cancel](/business/nouns/order/cancel) | | The record is not in a state that allows this Verb, so the call is refused. | [`refused`](/code/api/errors/refused) | Read the record, run the Verb that moves it to an allowed state, then retry. | [Order.cancel](/business/nouns/order/cancel) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Cancel the latest order. ``` **API** ```bash curl -X POST https://api.sb/petpantry.shop/orders/order_1/cancel \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/petpantry.shop", "order": { "$id": "https://api.sb/petpantry.shop/orders/order_1", "$type": "Order", "total": { "amount": 54, "currency": "USD" }, "status": "canceled" }, "action": { "$id": "https://api.sb/petpantry.shop/actions/action_1", "operation": "Order.cancel", "status": "done" }, "links": { "self": "https://api.sb/petpantry.shop/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const order = await $.Order.cancel({ order: 'order_1' }) ``` **CLI** ```bash npx startup-builder do Order.cancel --json '{"order":"order_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Order.cancel({ order: 'order_1' })" } } ``` # confirm URL: /business/nouns/order/confirm · Id: `verb:Order.confirm` · Call: `await $.Order.confirm({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Confirm records the Customer’s sign-off on delivered work, which closes the Order and earns the Startup its fee. Confirm records the [Customer](/business/nouns/customer)’s sign-off on delivered work, which closes the [Order](/business/nouns/order) and earns the [Startup](/business/nouns/startup) its fee. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `order` | [Order](/business/nouns/order) | Yes | The delivered Order. | | `lines` | `json` | No | The lines confirmed; every delivered line when absent. Each confirmed line bills on its own. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `order` | [Order](/business/nouns/order) | Yes | The closed Order. | ## Effects - Emits [`Order.confirmed`](/business/events/Order.confirmed). - Performed by the [Delivery Manager](/agents/operations/delivery-manager). - One-way (money): it waits out its delay window, and runs in the `send` and `do` modes. - Runs on its own when the acceptance window passes with no dispute. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Order.confirm](/business/nouns/order/confirm) | | The record is not in a state that allows this Verb, so the call is refused. | [`refused`](/code/api/errors/refused) | Read the record, run the Verb that moves it to an allowed state, then retry. | [Order.confirm](/business/nouns/order/confirm) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Medium: one-way, bounded (money) | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | 1 business hour, in which a watcher can pause, redirect or cancel it; then it runs. | | Limit | The spend [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) or [Mandate](/business/nouns/mandate) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Confirm the latest order. ``` **API** ```bash curl -X POST https://api.sb/petpantry.shop/orders/order_1/confirm \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/petpantry.shop", "order": { "$id": "https://api.sb/petpantry.shop/orders/order_1", "$type": "Order", "total": { "amount": 54, "currency": "USD" }, "status": "placed" }, "action": { "$id": "https://api.sb/petpantry.shop/actions/action_1", "operation": "Order.confirm", "status": "done" }, "links": { "self": "https://api.sb/petpantry.shop/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const order = await $.Order.confirm({ order: 'order_1' }) ``` **CLI** ```bash npx startup-builder do Order.confirm --json '{"order":"order_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Order.confirm({ order: 'order_1' })" } } ``` # deliver URL: /business/nouns/order/deliver · Id: `verb:Order.deliver` · Call: `await $.Order.deliver({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Deliver hands the finished work of a Service Order to its Customer and opens the acceptance window. Deliver hands the finished work of a [Service](/business/nouns/service) [Order](/business/nouns/order) to its [Customer](/business/nouns/customer) and opens the acceptance window. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `order` | [Order](/business/nouns/order) | Yes | The Order whose work is done. | | `work` | `json` | Yes | The deliverable and its evidence. | | `lines` | `json` | No | The lines delivered; every open line when absent. Each delivered line opens its own acceptance window. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `order` | [Order](/business/nouns/order) | Yes | The delivered Order. | ## Effects - Emits [`Order.delivered`](/business/events/Order.delivered). - Performed by the [Delivery Manager](/agents/operations/delivery-manager). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Runs the Evaluators the Outcome Contract declares before the Customer sees the work. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Order.deliver](/business/nouns/order/deliver) | | The record is not in a state that allows this Verb, so the call is refused. | [`refused`](/code/api/errors/refused) | Read the record, run the Verb that moves it to an allowed state, then retry. | [Order.deliver](/business/nouns/order/deliver) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Deliver the latest order. ``` **API** ```bash curl -X POST https://api.sb/patentpad.com/orders/order_1/deliver \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"work":{}}' ``` ```json { "api": "https://api.sb/patentpad.com", "order": { "$id": "https://api.sb/patentpad.com/orders/order_1", "$type": "Order", "total": { "amount": 499, "currency": "USD" }, "status": "placed" }, "action": { "$id": "https://api.sb/patentpad.com/actions/action_1", "operation": "Order.deliver", "status": "done" }, "links": { "self": "https://api.sb/patentpad.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const order = await $.Order.deliver({ order: 'order_1', work: {} }) ``` **CLI** ```bash npx startup-builder do Order.deliver --json '{"order":"order_1","work":{}}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Order.deliver({ order: 'order_1', work: {} })" } } ``` # dispute URL: /business/nouns/order/dispute · Id: `verb:Order.dispute` · Call: `await $.Order.dispute({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Dispute contests a delivered Order under its Outcome Contract and starts the remedy the contract names. `Order.dispute` contests a delivered [Order](/business/nouns/order) under its [Outcome Contract](/business/nouns/outcome-contract) and opens a [Dispute](/business/nouns/dispute) that starts the remedy the contract names. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `order` | [Order](/business/nouns/order) | Yes | The delivered Order. | | `reason` | `text` | Yes | What falls short of the promise. | | `lines` | `json` | No | The lines disputed; every delivered line when absent. Undisputed lines stay open to confirm. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `order` | [Order](/business/nouns/order) | Yes | The disputed Order. | ## Effects - Emits [`Order.disputed`](/business/events/Order.disputed). - Performed by the [Billing Specialist](/agents/finance/billing-specialist). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Holds the fee until the remedy completes. - Opens an Issue for the Customer Team. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The input does not match the schema of the operation. | [`invalid-input`](/code/api/errors/invalid-input) | Read the schema of the operation, then send every required field with the right type. | [Order.dispute](/business/nouns/order/dispute) | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Order.dispute](/business/nouns/order/dispute) | | The record is not in a state that allows this Verb, so the call is refused. | [`refused`](/code/api/errors/refused) | Read the record, run the Verb that moves it to an allowed state, then retry. | [Order.dispute](/business/nouns/order/dispute) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Dispute the latest order. ``` **API** ```bash curl -X POST https://api.sb/kilnbakery.com/orders/order_1/dispute \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"reason":"Example reason"}' ``` ```json { "api": "https://api.sb/kilnbakery.com", "order": { "$id": "https://api.sb/kilnbakery.com/orders/order_1", "$type": "Order", "total": { "amount": 9, "currency": "USD" }, "status": "placed" }, "action": { "$id": "https://api.sb/kilnbakery.com/actions/action_1", "operation": "Order.dispute", "status": "done" }, "links": { "self": "https://api.sb/kilnbakery.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const order = await $.Order.dispute({ order: 'order_1', reason: 'Example reason' }) ``` **CLI** ```bash npx startup-builder do Order.dispute --json '{"order":"order_1","reason":"Example reason"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Order.dispute({ order: 'order_1', reason: 'Example reason' })" } } ``` # fulfill URL: /business/nouns/order/fulfill · Id: `verb:Order.fulfill` · Call: `await $.Order.fulfill({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Fulfill grants what an Order bought: Entitlements for software and data, a shipment for goods. Fulfill grants what an [Order](/business/nouns/order) bought: [Entitlements](/business/nouns/entitlement) for software and data, a shipment for goods. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `order` | [Order](/business/nouns/order) | Yes | The paid Order. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `order` | [Order](/business/nouns/order) | Yes | The fulfilled Order. | ## Effects - Emits [`Order.fulfilled`](/business/events/Order.fulfilled). - Performed by the [Delivery Manager](/agents/operations/delivery-manager). - Two-way: it runs at once, in the `try`, `send` and `do` modes. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Order.fulfill](/business/nouns/order/fulfill) | | The record is not in a state that allows this Verb, so the call is refused. | [`refused`](/code/api/errors/refused) | Read the record, run the Verb that moves it to an allowed state, then retry. | [Order.fulfill](/business/nouns/order/fulfill) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Fulfill the latest order. ``` **API** ```bash curl -X POST https://api.sb/tutorloop.com/orders/order_1/fulfill \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/tutorloop.com", "order": { "$id": "https://api.sb/tutorloop.com/orders/order_1", "$type": "Order", "total": { "amount": 60, "currency": "USD" }, "status": "fulfilled" }, "action": { "$id": "https://api.sb/tutorloop.com/actions/action_1", "operation": "Order.fulfill", "status": "done" }, "links": { "self": "https://api.sb/tutorloop.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const order = await $.Order.fulfill({ order: 'order_1' }) ``` **CLI** ```bash npx startup-builder do Order.fulfill --json '{"order":"order_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Order.fulfill({ order: 'order_1' })" } } ``` # Order URL: /business/nouns/order · Id: `noun:order` > An Order is a Customer’s commitment to buy one or more Offers once, moving from placed to paid, fulfilled, and closed. An Order is a [Customer](/business/nouns/customer)’s commitment to buy one or more [Offers](/business/nouns/offer) once, moving from placed to paid, fulfilled, and closed. A recurring purchase is a [Subscription](/business/nouns/subscription), not an Order. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `total` | `money` | Yes | The amount charged. | | `status` | `string` | Yes | One of `placed`, `paid`, `fulfilled`, `closed`, `canceled`, or `refunded`. | | `merchantOfRecord` | [Party](/business/nouns/party) | No | The Party that charges and books the revenue. | | `outside` | `boolean` | No | Computed: true when its Customer shares no owner, Studio account, Agreement, or sibling chain with the Startup. | | `lines` | `json` | No | Each Offer bought, its quantity, amount and the Party that charges for it; a Service line carries its own verdict. | | `fulfillment` | `string` | No | Where a Service Order’s work stands between `paid` and `fulfilled`. | | `payment` | `string` | No | `authorized` when the Quote is accepted; `captured` on the Event the Outcome Contract `earns` names. | | `revisionsUsed` | `integer` | No | Revisions the Customer has asked for, counted against the Outcome Contract’s `revisions`. | | `risk` | `number` | No | The payment’s fraud risk score from 0 to 99 at screening, as Stripe scored it. | | `tax` | `money` | No | The sales tax, VAT or GST computed at placement for the buyer’s location and the Offer’s tax category. | | `taxJurisdiction` | `string` | No | Where the tax is owed, such as `US-CA` or `EU-DE`, or `none` when no registration applies. | | `brief` | `json` | No | The scope a Service Order bought, from its Quote request: sizes, inputs and turnaround. Intake checks the inputs against it. | | `dueAt` | `datetime` | No | When a Service Order’s work is due; time waiting on the Customer moves it later. | | `taxExemption` | [Credential](/business/nouns/credential) | No | The exemption or resale certificate that zeroed the tax, when one applies. | | `collectedBy` | `string` | No | The id of the venue that charged the buyer and pays the Startup; unset when the Startup’s own checkout collected. | ## Object ```json { "$id": "https://api.sb/quietcopy.com/orders/order_1", "$type": "Order", "total": { "amount": 39, "currency": "USD" }, "status": "placed", "merchantOfRecord": "party_1", "outside": true, "lines": {}, "fulfillment": "intake", "payment": "authorized", "revisionsUsed": 1, "risk": 1, "tax": { "amount": 39, "currency": "USD" }, "taxJurisdiction": "US-CA", "brief": {}, "dueAt": "2026-10-22T12:00:00Z", "taxExemption": "credential_1", "collectedBy": "aws-marketplace" } ``` ## Relationships - An Order **buys** many [Offers](/business/nouns/offer): an Order commits to buying one or more [Offers](/business/nouns/offer) once. `buys`, inverse [`orderedIn`](/business/nouns/offer#rel-ordered-in). - An Order **has** many [Disputes](/business/nouns/dispute): the Order whose delivery or charge the [Dispute](/business/nouns/dispute) contests. `disputes`, inverse [`contests`](/business/nouns/dispute#rel-contests). - An Order **is placed by** one [Customer](/business/nouns/customer): a [Customer](/business/nouns/customer) commits to one-time purchases as Orders. `placedBy`, inverse [`places`](/business/nouns/customer#rel-places). - An Order **has** one [Quote](/business/nouns/quote): the Order the [Quote](/business/nouns/quote) becomes when the buyer accepts it before it expires. `quote`, inverse [`acceptedAs`](/business/nouns/quote#rel-accepted-as). ## Lifecycle | State | Meaning | Moves to | | --- | --- | --- | | `placed` (first) | The Customer committed, with the Offer Version and price fixed; nothing is charged yet. | `paid` by [Order.pay](/business/nouns/order/pay); `canceled` by [Order.cancel](/business/nouns/order/cancel) | | `paid` | Its amount is settled and its Entries posted; a Service Order’s work runs in `fulfillment`. | `fulfilled` by [Order.fulfill](/business/nouns/order/fulfill); `closed` by [Order.confirm](/business/nouns/order/confirm); `canceled` by [Order.cancel](/business/nouns/order/cancel); `refunded` by [Order.refund](/business/nouns/order/refund) | | `fulfilled` | What it bought is granted: Entitlements for software and data, or a shipment for goods. | `closed` by [Order.confirm](/business/nouns/order/confirm); `refunded` by [Order.refund](/business/nouns/order/refund) | | `closed` | The Customer signed off, which earns the Startup its fee. | `refunded` by [Order.refund](/business/nouns/order/refund) | | `canceled` | Ended before fulfillment, with any payment returned in full. | None: it ends here. | | `refunded` | Its payment returned in full, with the reversing Entries posted; a partial refund keeps its state. | None: it ends here. | ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Order.cancel](/business/nouns/order/cancel) | Cancel ends an Order before fulfillment and returns any payment in full. | [Customer](/business/nouns/customer) | [`Order.canceled`](/business/events/Order.canceled) | Two-way: `try`, `send`, `do` | | [Order.confirm](/business/nouns/order/confirm) | Confirm records the Customer’s sign-off on delivered work, which closes the Order and earns the Startup its fee. | [Delivery Manager](/agents/operations/delivery-manager) | [`Order.confirmed`](/business/events/Order.confirmed) | One-way (money): `send`, `do` | | [Order.deliver](/business/nouns/order/deliver) | Deliver hands the finished work of a Service Order to its Customer and opens the acceptance window. | [Delivery Manager](/agents/operations/delivery-manager) | [`Order.delivered`](/business/events/Order.delivered) | Two-way: `try`, `send`, `do` | | [Order.dispute](/business/nouns/order/dispute) | Dispute contests a delivered Order under its Outcome Contract and starts the remedy the contract names. | [Billing Specialist](/agents/finance/billing-specialist) | [`Order.disputed`](/business/events/Order.disputed) | Two-way: `try`, `send`, `do` | | [Order.fulfill](/business/nouns/order/fulfill) | Fulfill grants what an Order bought: Entitlements for software and data, a shipment for goods. | [Delivery Manager](/agents/operations/delivery-manager) | [`Order.fulfilled`](/business/events/Order.fulfilled) | Two-way: `try`, `send`, `do` | | [Order.pay](/business/nouns/order/pay) | Pay settles an Order’s amount through the Startup’s payment account and posts the matching Entries. | [Billing Specialist](/agents/finance/billing-specialist) | [`Order.paid`](/business/events/Order.paid) | One-way (money): `send`, `do` | | [Order.place](/business/nouns/order/place) | Place commits a Customer to buy an Offer once and records the Offer Version and price at that moment. | [Founder](/agents/founding/founder) | [`Order.placed`](/business/events/Order.placed) | Two-way: `try`, `send`, `do` | | [Order.refund](/business/nouns/order/refund) | Refund returns all or part of an Order’s payment to the Customer and posts the reversing Entries. | [Billing Specialist](/agents/finance/billing-specialist) | [`Order.refunded`](/business/events/Order.refunded) | One-way (money, customer): `send`, `do` | | [Order.revise](/business/nouns/order/revise) | Revise sends delivered lines back for one counted revision, with the changes the Customer asks for. | [Delivery Manager](/agents/operations/delivery-manager) | [`Order.revised`](/business/events/Order.revised) | Two-way: `try`, `send`, `do` | | [Order.screen](/business/nouns/order/screen) | Screen scores an Order’s payment before it is charged and allows, authenticates, holds or blocks it by the Startup’s risk Policy. | [Risk Analyst](/agents/operations/risk-analyst) | [`Order.screened`](/business/events/Order.screened) | Two-way: `try`, `send`, `do` | | [Order.start](/business/nouns/order/start) | Start checks a Service Order’s inputs against its brief, then moves it from intake to working and starts its deadline. | [Delivery Manager](/agents/operations/delivery-manager) | [`Order.started`](/business/events/Order.started) | Two-way: `try`, `send`, `do` | | [Order.create](/business/nouns/order/create) | Creates an Order. Inherited from [Noun](/business/nouns/noun). | None. | `Order.created` | Two-way: `try`, `send`, `do` | | [Order.get](/business/nouns/order/get) | Returns one Order by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Order.list](/business/nouns/order/list) | Returns Orders, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Order.update](/business/nouns/order/update) | Changes the given properties of an Order. Inherited from [Noun](/business/nouns/noun). | None. | `Order.updated` | Two-way: `try`, `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Order.create` | Yes | Yes | Yes | No | | `Order.get` | Yes | Yes | Yes | Yes | | `Order.list` | Yes | Yes | Yes | Yes | | `Order.update` | Yes | Yes | Yes | No | | `Order.cancel` | Yes | Yes | Yes | No | | `Order.confirm` | Yes | No | No | No | | `Order.deliver` | Yes | Yes | Yes | No | | `Order.dispute` | Yes | Yes | Yes | No | | `Order.fulfill` | Yes | Yes | Yes | No | | `Order.pay` | Yes | No | No | No | | `Order.place` | Yes | Yes | Yes | No | | `Order.refund` | Yes | No | No | No | | `Order.revise` | Yes | Yes | Yes | No | | `Order.screen` | Yes | Yes | Yes | No | | `Order.start` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Place the latest order with an offer. ``` **API** ```bash curl -X POST https://api.sb/ledgerlark.com/orders/place \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"offer":"offer_1"}' ``` ```json { "api": "https://api.sb/ledgerlark.com", "order": { "$id": "https://api.sb/ledgerlark.com/orders/order_1", "$type": "Order", "total": { "amount": 400, "currency": "USD" }, "status": "placed" }, "action": { "$id": "https://api.sb/ledgerlark.com/actions/action_1", "operation": "Order.place", "status": "done" }, "links": { "self": "https://api.sb/ledgerlark.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const order = await $.Order.place({ offer: 'offer_1' }) ``` **CLI** ```bash npx startup-builder do Order.place --json '{"offer":"offer_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Order.place({ offer: 'offer_1' })" } } ``` ## Example A dropship store takes an Order for two espresso-machine filters, `total: 38.00`. It moves to `paid` at checkout, `fulfilled` when the parcel ships, and `closed` when tracking shows delivery. # pay URL: /business/nouns/order/pay · Id: `verb:Order.pay` · Call: `await $.Order.pay({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Pay settles an Order’s amount through the Startup’s payment account and posts the matching Entries. Pay settles an [Order](/business/nouns/order)’s amount through the [Startup](/business/nouns/startup)’s payment account and posts the matching [Entries](/business/nouns/entry). ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `order` | [Order](/business/nouns/order) | Yes | The placed Order. | | `paymentMethod` | `string` | No | The saved method to charge. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `order` | [Order](/business/nouns/order) | Yes | The paid Order. | ## Effects - Emits [`Order.paid`](/business/events/Order.paid). - Performed by the [Billing Specialist](/agents/finance/billing-specialist). - One-way (money): it waits out its delay window, and runs in the `send` and `do` modes. - On an Offer with `credit`, issues a `paid` Credit Grant to the Customer for that amount. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The operation is part of an Offer the caller has not accepted or paid for. | [`payment-required`](/code/api/errors/payment-required) | Accept the Offer named in the response, then retry the call. | [Offer.accept](/business/nouns/offer/accept) | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Order.pay](/business/nouns/order/pay) | | The record is not in a state that allows this Verb, so the call is refused. | [`refused`](/code/api/errors/refused) | Read the record, run the Verb that moves it to an allowed state, then retry. | [Order.pay](/business/nouns/order/pay) | | Stripe disabled charges on the Startup’s payment account because a requirement passed its deadline. | [`charges-disabled`](/code/api/errors/charges-disabled) | Have the owner of record complete the open requirement Task; charges and paid Offers resume on re-enable. | [Order.pay](/business/nouns/order/pay) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Medium: one-way, bounded (money) | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | 1 business hour, in which a watcher can pause, redirect or cancel it; then it runs. | | Limit | The spend [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) or [Mandate](/business/nouns/mandate) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Pay the latest order. ``` **API** ```bash curl -X POST https://api.sb/tutorloop.com/orders/order_1/pay \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/tutorloop.com", "order": { "$id": "https://api.sb/tutorloop.com/orders/order_1", "$type": "Order", "total": { "amount": 60, "currency": "USD" }, "status": "paid" }, "action": { "$id": "https://api.sb/tutorloop.com/actions/action_1", "operation": "Order.pay", "status": "done" }, "links": { "self": "https://api.sb/tutorloop.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const order = await $.Order.pay({ order: 'order_1' }) ``` **CLI** ```bash npx startup-builder do Order.pay --json '{"order":"order_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Order.pay({ order: 'order_1' })" } } ``` # place URL: /business/nouns/order/place · Id: `verb:Order.place` · Call: `await $.Order.place({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Place commits a Customer to buy an Offer once and records the Offer Version and price at that moment. Place commits a [Customer](/business/nouns/customer) to buy an [Offer](/business/nouns/offer) once and records the Offer [Version](/business/nouns/version) and price at that moment. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `offer` | [Offer](/business/nouns/offer) | Yes | The Offer to buy. | | `quantity` | `integer` | No | Units. Defaults to 1. | | `promotionCode` | `string` | No | A promotion code the buyer typed; applies its Coupon when the Coupon covers the Offer. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `order` | [Order](/business/nouns/order) | Yes | The placed Order. | ## Effects - Emits [`Order.placed`](/business/events/Order.placed). - Performed by the [Founder](/agents/founding/founder). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Makes the party a Customer when it is not one yet. - Says before charging whether the Startup can deliver. - Computes tax through Stripe Tax on the Startup’s own account, as seller of record, and records it on the Order before payment. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The input does not match the schema of the operation. | [`invalid-input`](/code/api/errors/invalid-input) | Read the schema of the operation, then send every required field with the right type. | [Order.place](/business/nouns/order/place) | | The operation is part of an Offer the caller has not accepted or paid for. | [`payment-required`](/code/api/errors/payment-required) | Accept the Offer named in the response, then retry the call. | [Offer.accept](/business/nouns/offer/accept) | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Order.place](/business/nouns/order/place) | | The record is not in a state that allows this Verb, so the call is refused. | [`refused`](/code/api/errors/refused) | Read the record, run the Verb that moves it to an allowed state, then retry. | [Order.place](/business/nouns/order/place) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Place the latest order with an offer. ``` **API** ```bash curl -X POST https://api.sb/ledgerlark.com/orders/place \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"offer":"offer_1"}' ``` ```json { "api": "https://api.sb/ledgerlark.com", "order": { "$id": "https://api.sb/ledgerlark.com/orders/order_1", "$type": "Order", "total": { "amount": 400, "currency": "USD" }, "status": "placed" }, "action": { "$id": "https://api.sb/ledgerlark.com/actions/action_1", "operation": "Order.place", "status": "done" }, "links": { "self": "https://api.sb/ledgerlark.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const order = await $.Order.place({ offer: 'offer_1' }) ``` **CLI** ```bash npx startup-builder do Order.place --json '{"offer":"offer_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Order.place({ offer: 'offer_1' })" } } ``` # refund URL: /business/nouns/order/refund · Id: `verb:Order.refund` · Call: `await $.Order.refund({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Refund returns all or part of an Order’s payment to the Customer and posts the reversing Entries. Refund returns all or part of an [Order](/business/nouns/order)’s payment to the [Customer](/business/nouns/customer) and posts the reversing [Entries](/business/nouns/entry). ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `order` | [Order](/business/nouns/order) | Yes | The paid Order. | | `amount` | `money` | No | The amount. Defaults to the full payment. | | `reason` | `text` | Yes | Why the money goes back. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `order` | [Order](/business/nouns/order) | Yes | The refunded Order. | ## Effects - Emits [`Order.refunded`](/business/events/Order.refunded). - Performed by the [Billing Specialist](/agents/finance/billing-specialist). - One-way (money, customer): it waits out its delay window, and runs in the `send` and `do` modes. - Checks the refund Limit; above it, opens an Approval and the Action waits. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The input does not match the schema of the operation. | [`invalid-input`](/code/api/errors/invalid-input) | Read the schema of the operation, then send every required field with the right type. | [Order.refund](/business/nouns/order/refund) | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Order.refund](/business/nouns/order/refund) | | The record is not in a state that allows this Verb, so the call is refused. | [`refused`](/code/api/errors/refused) | Read the record, run the Verb that moves it to an allowed state, then retry. | [Order.refund](/business/nouns/order/refund) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Medium: one-way, bounded (money, customer) | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | 1 business hour, in which a watcher can pause, redirect or cancel it; then it runs. | | Limit | The spend [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) or [Mandate](/business/nouns/mandate) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Refund the latest order. ``` **API** ```bash curl -X POST https://api.sb/kilnbakery.com/orders/order_1/refund \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"reason":"Example reason"}' ``` ```json { "api": "https://api.sb/kilnbakery.com", "order": { "$id": "https://api.sb/kilnbakery.com/orders/order_1", "$type": "Order", "total": { "amount": 9, "currency": "USD" }, "status": "refunded" }, "action": { "$id": "https://api.sb/kilnbakery.com/actions/action_1", "operation": "Order.refund", "status": "done" }, "links": { "self": "https://api.sb/kilnbakery.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const order = await $.Order.refund({ order: 'order_1', reason: 'Example reason' }) ``` **CLI** ```bash npx startup-builder do Order.refund --json '{"order":"order_1","reason":"Example reason"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Order.refund({ order: 'order_1', reason: 'Example reason' })" } } ``` Guides that call it: [Refund a customer](/systems/finance/refund-a-customer). # revise URL: /business/nouns/order/revise · Id: `verb:Order.revise` · Call: `await $.Order.revise({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Revise sends delivered lines back for one counted revision, with the changes the Customer asks for. Revise sends delivered lines back for one counted revision, with the changes the [Customer](/business/nouns/customer) asks for. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `order` | [Order](/business/nouns/order) | Yes | The delivered Order. | | `lines` | `json` | No | The lines sent back; every delivered line when absent. | | `changes` | `text` | Yes | What the Customer wants changed, such as a shorter summary. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `order` | [Order](/business/nouns/order) | Yes | The Order, its `fulfillment` set to `revising`. | ## Effects - Emits [`Order.revised`](/business/events/Order.revised). - Performed by the [Delivery Manager](/agents/operations/delivery-manager). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Counts against the Outcome Contract’s `revisions`; past the allowance, the Order is disputed and the remedy starts. - Pauses the acceptance window until the revised work is delivered. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Order.revise](/business/nouns/order/revise) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Revise the latest order. ``` **API** ```bash curl -X POST https://api.sb/tutorloop.com/orders/order_1/revise \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"changes":"Example changes"}' ``` ```json { "api": "https://api.sb/tutorloop.com", "order": { "$id": "https://api.sb/tutorloop.com/orders/order_1", "$type": "Order", "total": { "amount": 60, "currency": "USD" }, "status": "placed" }, "action": { "$id": "https://api.sb/tutorloop.com/actions/action_1", "operation": "Order.revise", "status": "done" }, "links": { "self": "https://api.sb/tutorloop.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const order = await $.Order.revise({ order: 'order_1', changes: 'Example changes' }) ``` **CLI** ```bash npx startup-builder do Order.revise --json '{"order":"order_1","changes":"Example changes"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Order.revise({ order: 'order_1', changes: 'Example changes' })" } } ``` # screen URL: /business/nouns/order/screen · Id: `verb:Order.screen` · Call: `await $.Order.screen({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Screen scores an Order’s payment before it is charged and allows, authenticates, holds or blocks it by the Startup’s risk Policy. Screen scores an [Order](/business/nouns/order)’s payment before it is charged and allows, authenticates, holds or blocks it by the [Startup](/business/nouns/startup)’s risk [Policy](/business/nouns/policy). ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `order` | [Order](/business/nouns/order) | Yes | The placed Order whose payment is screened. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `outcome` | `string` | Yes | `allow` charges, `authenticate` asks the buyer to confirm with their card issuer, `review` waits for an Approval, `block` cancels. | | `risk` | `number` | Yes | The payment’s risk score from 0 to 99, as Stripe scored it. | | `rule` | `string` | No | The risk Policy rule that decided the outcome, when one did. | | `order` | [Order](/business/nouns/order) | Yes | The Order screened. | ## Effects - Emits [`Order.screened`](/business/events/Order.screened). - Performed by the [Risk Analyst](/agents/operations/risk-analyst). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - An Order held for `review` opens an Approval for the Risk Analyst and is not charged until approved. - A blocked Order is canceled and never charged. - An early fraud warning stops fulfillment at once and, at or below the dispute fee, proposes a refund that waits its window. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Order.screen](/business/nouns/order/screen) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Screen the latest order. ``` **API** ```bash curl -X POST https://api.sb/quietcopy.com/orders/order_1/screen \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/quietcopy.com", "outcome": "allow", "risk": 1, "rule": "Example rule", "order": { "$id": "https://api.sb/quietcopy.com/orders/order_1", "$type": "Order", "total": { "amount": 39, "currency": "USD" }, "status": "placed" }, "action": { "$id": "https://api.sb/quietcopy.com/actions/action_1", "operation": "Order.screen", "status": "done" }, "links": { "self": "https://api.sb/quietcopy.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { outcome, risk, rule, order } = await $.Order.screen({ order: 'order_1' }) ``` **CLI** ```bash npx startup-builder do Order.screen --json '{"order":"order_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Order.screen({ order: 'order_1' })" } } ``` # start URL: /business/nouns/order/start · Id: `verb:Order.start` · Call: `await $.Order.start({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Start checks a Service Order’s inputs against its brief, then moves it from intake to working and starts its deadline. Start checks a [Service](/business/nouns/service) [Order](/business/nouns/order)’s inputs against its brief, then moves it from intake to working and starts its deadline. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `order` | [Order](/business/nouns/order) | Yes | The Order in intake. | | `received` | `json` | Yes | What the Customer supplied, measured as the brief measures it, such as a 79,400-word manuscript. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `order` | [Order](/business/nouns/order) | Yes | The Order, its `fulfillment` set to `working`, or still `intake` while a Question is open. | ## Effects - Emits [`Order.started`](/business/events/Order.started). - Performed by the [Delivery Manager](/agents/operations/delivery-manager). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Asks the Customer one Question for every missing input; the deadline starts when the answer arrives. - Sets `dueAt` from the brief’s turnaround, counted from the moment the work starts. - Quotes work beyond the brief on a new Quote on the same Deal; the Order keeps its accepted lines. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Order.start](/business/nouns/order/start) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Start the latest order. ``` **API** ```bash curl -X POST https://api.sb/kilnbakery.com/orders/order_1/start \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"received":{}}' ``` ```json { "api": "https://api.sb/kilnbakery.com", "order": { "$id": "https://api.sb/kilnbakery.com/orders/order_1", "$type": "Order", "total": { "amount": 9, "currency": "USD" }, "status": "placed" }, "action": { "$id": "https://api.sb/kilnbakery.com/actions/action_1", "operation": "Order.start", "status": "done" }, "links": { "self": "https://api.sb/kilnbakery.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const order = await $.Order.start({ order: 'order_1', received: {} }) ``` **CLI** ```bash npx startup-builder do Order.start --json '{"order":"order_1","received":{}}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Order.start({ order: 'order_1', received: {} })" } } ``` # Organization URL: /business/nouns/organization · Id: `noun:organization` > An Organization is an outside party as one Startup knows it, keyed by its domain, such as an employer or a vendor. An Organization is an outside party as one [Startup](/business/nouns/startup) knows it, keyed by its domain, such as an employer or a vendor. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `name` | `string` | Yes | The name it trades under. | | `hostname` | `string` | No | The web domain that keys it. | Inherits from [Party](/business/nouns/party), which adds no properties of its own. ## Object ```json { "$id": "https://api.sb/ledgerlark.com/organizations/organization_1", "$type": "Organization", "name": "LedgerLark", "hostname": "ledgerlark.com" } ``` ## Relationships - An Organization **has** many [Bills](/business/nouns/bill): a [Bill](/business/nouns/bill) is owed to one outside Organization, whose page lists every Bill the [Startup](/business/nouns/startup) owes it. `bills`, inverse [`owedTo`](/business/nouns/bill#rel-owed-to). - An Organization **has** many [Deals](/business/nouns/deal): each [Deal](/business/nouns/deal) has one buying Organization on the other side. `deals`, inverse [`courts`](/business/nouns/deal#rel-courts). - An Organization’s **people** are many [Contacts](/business/nouns/contact): a [Contact](/business/nouns/contact) works for one Organization, as this [Startup](/business/nouns/startup) knows it. `people`, inverse [`worksAt`](/business/nouns/contact#rel-works-at). - An Organization **is reserved by** one [Partner](/business/nouns/partner): an Organization a [Partner](/business/nouns/partner) reserved before referring it, for the `partner.reservationWindow` [Setting](/business/nouns/setting) (90 days by default); outbound skips it. `reservedBy`, inverse [`reserves`](/business/nouns/partner#rel-reserves). - An Organization **resolves to** one [Company](/business/nouns/company): each [Startup](/business/nouns/startup)’s own view of an outside party resolves to the one legal entity behind it. `resolvesTo`, inverse [`knownAs`](/business/nouns/company#rel-known-as). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Organization.merge](/business/nouns/organization/merge) | Merge joins a duplicate Organization into another, keeping every Contact, Deal and Event on the one that remains. | [Sales Lead](/agents/sales/sales-lead) | [`Organization.merged`](/business/events/Organization.merged) | One-way: `send`, `do` | | [Organization.create](/business/nouns/organization/create) | Creates an Organization. Inherited from [Noun](/business/nouns/noun). | None. | `Organization.created` | Two-way: `try`, `send`, `do` | | [Organization.get](/business/nouns/organization/get) | Returns one Organization by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Organization.list](/business/nouns/organization/list) | Returns Organizations, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Organization.update](/business/nouns/organization/update) | Changes the given properties of an Organization. Inherited from [Noun](/business/nouns/noun). | None. | `Organization.updated` | Two-way: `try`, `send`, `do` | | [Organization.delete](/business/nouns/organization/delete) | Deletes an Organization; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Organization.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Organization.create` | Yes | Yes | Yes | No | | `Organization.get` | Yes | Yes | Yes | Yes | | `Organization.list` | Yes | Yes | Yes | Yes | | `Organization.update` | Yes | Yes | Yes | No | | `Organization.delete` | Yes | Yes | Yes | No | | `Organization.merge` | Yes | No | No | No | ## Call it **Ask** ```text Merge my organization. ``` **API** ```bash curl -X POST https://api.sb/patentpad.com/organizations/organization_1/merge \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"into":"organization_1"}' ``` ```json { "api": "https://api.sb/patentpad.com", "organization": { "$id": "https://api.sb/patentpad.com/organizations/organization_1", "$type": "Organization", "name": "PatentPad" }, "action": { "$id": "https://api.sb/patentpad.com/actions/action_1", "operation": "Organization.merge", "status": "done" }, "links": { "self": "https://api.sb/patentpad.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const organization = await $.Organization.merge({ organization: 'organization_1', into: 'organization_1' }) ``` **CLI** ```bash npx startup-builder do Organization.merge --json '{"organization":"organization_1","into":"organization_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Organization.merge({ organization: 'organization_1', into: 'organization_1' })" } } ``` ## Example To a recruiting-agency [SaaS](/products/templates/saas), the Organization keyed by `northpeak-talent.com` employs four [Contacts](/business/nouns/contact) and is the buyer on one [Deal](/business/nouns/deal). # merge URL: /business/nouns/organization/merge · Id: `verb:Organization.merge` · Call: `await $.Organization.merge({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Merge joins a duplicate Organization into another, keeping every Contact, Deal and Event on the one that remains. Merge joins a duplicate [Organization](/business/nouns/organization) into another, keeping every [Contact](/business/nouns/contact), [Deal](/business/nouns/deal) and [Event](/business/nouns/event) on the one that remains. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `organization` | [Organization](/business/nouns/organization) | Yes | The duplicate. | | `into` | [Organization](/business/nouns/organization) | Yes | The Organization that remains. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `organization` | [Organization](/business/nouns/organization) | Yes | The remaining Organization. | ## Effects - Emits [`Organization.merged`](/business/events/Organization.merged). - Performed by the [Sales Lead](/agents/sales/sales-lead). - One-way: it waits out its delay window, and runs in the `send` and `do` modes. - Keeps the merged id as an alias; nothing is deleted. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Organization.merge](/business/nouns/organization/merge) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Medium: one-way, bounded | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | 1 business hour, in which a watcher can pause, redirect or cancel it; then it runs. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Merge my organization. ``` **API** ```bash curl -X POST https://api.sb/patentpad.com/organizations/organization_1/merge \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"into":"organization_1"}' ``` ```json { "api": "https://api.sb/patentpad.com", "organization": { "$id": "https://api.sb/patentpad.com/organizations/organization_1", "$type": "Organization", "name": "PatentPad" }, "action": { "$id": "https://api.sb/patentpad.com/actions/action_1", "operation": "Organization.merge", "status": "done" }, "links": { "self": "https://api.sb/patentpad.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const organization = await $.Organization.merge({ organization: 'organization_1', into: 'organization_1' }) ``` **CLI** ```bash npx startup-builder do Organization.merge --json '{"organization":"organization_1","into":"organization_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Organization.merge({ organization: 'organization_1', into: 'organization_1' })" } } ``` # Outcome Contract URL: /business/nouns/outcome-contract · Id: `noun:outcome-contract` > An Outcome Contract is the terms on an Offer that warrant a Service’s result: done, acceptance, assurance, remedy, and earnings. An Outcome Contract is the terms on an [Offer](/business/nouns/offer) that warrant a [Service](/business/nouns/service)’s result: done, acceptance, assurance, remedy, and earnings. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `done` | `text` | Yes | The state or Event that counts as done. | | `accept` | `text` | Yes | Who accepts the result, and within what window. | | `remedy` | `text` | Yes | What happens on a miss: redo, refund, or credit. | | `revisions` | `integer` | No | How many times the Customer may send work back before the remedy applies, such as 1. | | `silence` | `string` | No | What the Customer’s silence means once the acceptance window passes. | | `earns` | `string` | No | The Event that captures payment and earns the fee. | | `assurance` | `json` | No | The Evaluators that check done before every delivery, and the share of work a person grades, such as 2%. | | `window` | `string` | No | How long the Customer has to confirm, revise or dispute each delivery, as an ISO duration. | ## Object ```json { "$id": "https://api.sb/patentpad.com/outcome-contracts/outcome_contract_1", "$type": "OutcomeContract", "done": "Order.accepted", "accept": "The buyer, within 5 business days of delivery", "remedy": "Redo once, then refund in full", "revisions": 1, "silence": "accepts", "earns": "Order.confirmed", "assurance": {}, "window": "P3D" } ``` ## Relationships - An Outcome Contract **governs** one [Offer](/business/nouns/offer): an Outcome Contract warrants the result an [Offer](/business/nouns/offer) sells: its done state, acceptance, assurance and remedy. `governs`, inverse [`governedBy`](/business/nouns/offer#rel-governed-by). - An Outcome Contract **is verified by** many [Evaluators](/business/nouns/evaluator): [Evaluators](/business/nouns/evaluator) grade delivered work against an Outcome Contract’s done state before the [Customer](/business/nouns/customer) accepts it. `verifiedBy`, inverse [`verifies`](/business/nouns/evaluator#rel-verifies). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [OutcomeContract.get](/business/nouns/outcome-contract/get) | Returns one Outcome Contract by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [OutcomeContract.list](/business/nouns/outcome-contract/list) | Returns Outcome Contracts, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [OutcomeContract.update](/business/nouns/outcome-contract/update) | Changes the given properties of an Outcome Contract. Inherited from [Noun](/business/nouns/noun). | None. | `OutcomeContract.updated` | Two-way: `try`, `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `OutcomeContract.get` | Yes | Yes | Yes | Yes | | `OutcomeContract.list` | Yes | Yes | Yes | Yes | | `OutcomeContract.update` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Show me the latest outcome contract. ``` **API** ```bash curl https://api.sb/tutorloop.com/outcome-contracts/outcome_contract_1 \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/tutorloop.com", "$type": "OutcomeContract", "$id": "https://api.sb/tutorloop.com/outcome-contracts/outcome_contract_1", "outcomeContract": { "$id": "https://api.sb/tutorloop.com/outcome-contracts/outcome_contract_1", "$type": "OutcomeContract", "done": "Order.accepted", "accept": "The buyer, within 5 business days of delivery", "remedy": "Redo once, then refund in full" }, "links": { "self": "https://api.sb/tutorloop.com/outcome-contracts/outcome_contract_1", "up": "https://api.sb/tutorloop.com/outcome-contracts" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const outcomeContract = await $.OutcomeContract.get({ id: 'outcome_contract_1' }) ``` **CLI** ```bash npx startup-builder do OutcomeContract.get --json '{"id":"outcome_contract_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.OutcomeContract.get({ id: 'outcome_contract_1' })" } } ``` ## Example A bookkeeping Service's Outcome Contract defines done as a reconciled month, accepted by the [Customer](/business/nouns/customer) within 5 days, with one redo as the remedy. # Page URL: /business/nouns/page · Id: `noun:page` > A Page is an addressable page of a Site, of a named type such as pricing, about one Thing or each member of a Collection. A Page is an addressable page of a [Site](/business/nouns/site), of a named type such as pricing, about one [Thing](/business/nouns/thing) or each member of a [Collection](/business/nouns/collection). A [Template](/business/nouns/template) renders it. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `path` | `string` | Yes | The path under its Site, such as `/pricing`. | | `kind` | `string` | No | The page type, such as `landing`, `pricing`, or `terms`. | | `from` | `string` | No | Lineage: the slot it compiles from, as `Hypothesis#@v`. | ## Object ```json { "$id": "https://api.sb/shiftnote.app/pages/page_1", "$type": "Page", "path": "/", "kind": "landing", "from": "Hypothesis#approach@v1" } ``` ## Relationships - A Page **is contained in** one [Site](/business/nouns/site): a [Site](/business/nouns/site) serves its Pages, each at its own path. `containedIn`, inverse [`contains`](/business/nouns/site#rel-contains). - A Page **displays** many pieces of [Content](/business/nouns/content): Pages display published [Content](/business/nouns/content); one piece appears on many Pages. `displays`, inverse [`displayedOn`](/business/nouns/content#rel-displayed-on). - A Page **embeds** many [Forms](/business/nouns/form): [Forms](/business/nouns/form) sit on Pages; one Form appears on many Pages. `embeds`, inverse [`embeddedIn`](/business/nouns/form#rel-embedded-in). - A Page **is rendered with** one [Template](/business/nouns/template): a [Template](/business/nouns/template) fills one Page per [Thing](/business/nouns/thing) or per member of a [Collection](/business/nouns/collection). `renderedWith`, inverse [`renders`](/business/nouns/template#rel-renders). - A Page **targets** many [Keywords](/business/nouns/keyword): a Page is written to rank for, or be cited on, its [Keywords](/business/nouns/keyword). `targets`, inverse [`targetedBy`](/business/nouns/keyword#rel-targeted-by). - A Page **uses** many [Components](/business/nouns/component): a Page is assembled from [Components](/business/nouns/component), each filled from records. `uses`, inverse [`usedOn`](/business/nouns/component#rel-used-on). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Page.create](/business/nouns/page/create) | Creates a Page. Inherited from [Noun](/business/nouns/noun). | None. | `Page.created` | Two-way: `try`, `send`, `do` | | [Page.get](/business/nouns/page/get) | Returns one Page by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Page.list](/business/nouns/page/list) | Returns Pages, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Page.update](/business/nouns/page/update) | Changes the given properties of a Page. Inherited from [Noun](/business/nouns/noun). | None. | `Page.updated` | Two-way: `try`, `send`, `do` | | [Page.delete](/business/nouns/page/delete) | Deletes a Page; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Page.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Page.create` | Yes | Yes | Yes | No | | `Page.get` | Yes | Yes | Yes | Yes | | `Page.list` | Yes | Yes | Yes | Yes | | `Page.update` | Yes | Yes | Yes | No | | `Page.delete` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Add a page to RouteWise. ``` **API** ```bash curl -X POST https://api.sb/routewise.dev/pages \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"path":"/"}' ``` ```json { "api": "https://api.sb/routewise.dev", "page": { "$id": "https://api.sb/routewise.dev/pages/page_1", "$type": "Page", "path": "/" }, "action": { "$id": "https://api.sb/routewise.dev/actions/action_1", "operation": "Page.create", "status": "done" }, "links": { "self": "https://api.sb/routewise.dev/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const page = await $.Page.create({ path: '/' }) ``` **CLI** ```bash npx startup-builder do Page.create --json '{"path":"/"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Page.create({ path: '/' })" } } ``` ## Example `/inspectors/denver` is a Page of kind `city` on a home-inspector directory, one per member of a [Collection](/business/nouns/collection) of cities. Adding an inspector updates it with no edit. # Partner URL: /business/nouns/partner · Id: `noun:partner` > A Partner is an outside Organization that is party to an Agreement with a Startup, supplying it, distributing its Offers, or both. A Partner is an outside [Organization](/business/nouns/organization) that is party to an [Agreement](/business/nouns/agreement) with a [Startup](/business/nouns/startup), supplying it, distributing its [Offers](/business/nouns/offer), or both. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `side` | `string` | Yes | One of `supply`, `distribution`, or `both`. |
Inherited from [Organization](/business/nouns/organization): 2 properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `name` | `string` | Yes | The name it trades under. | | `hostname` | `string` | No | The web domain that keys it. |
## Object ```json { "$id": "https://api.sb/kilnbakery.com/partners/partner_1", "$type": "Partner", "name": "Kiln Bakery", "hostname": "kilnbakery.com", "side": "supply" } ``` ## Relationships - A Partner **reserves** many [Organizations](/business/nouns/organization): an [Organization](/business/nouns/organization) a Partner reserved before referring it, for the `partner.reservationWindow` [Setting](/business/nouns/setting) (90 days by default); outbound skips it. `reserves`, inverse [`reservedBy`](/business/nouns/organization#rel-reserved-by). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Partner.create](/business/nouns/partner/create) | Creates a Partner. Inherited from [Noun](/business/nouns/noun). | None. | `Partner.created` | Two-way: `try`, `send`, `do` | | [Partner.get](/business/nouns/partner/get) | Returns one Partner by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Partner.list](/business/nouns/partner/list) | Returns Partners, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Partner.update](/business/nouns/partner/update) | Changes the given properties of a Partner. Inherited from [Noun](/business/nouns/noun). | None. | `Partner.updated` | Two-way: `try`, `send`, `do` | | [Partner.delete](/business/nouns/partner/delete) | Deletes a Partner; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Partner.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Partner.create` | Yes | Yes | Yes | No | | `Partner.get` | Yes | Yes | Yes | Yes | | `Partner.list` | Yes | Yes | Yes | Yes | | `Partner.update` | Yes | Yes | Yes | No | | `Partner.delete` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Add a partner to PetPantry. ``` **API** ```bash curl -X POST https://api.sb/petpantry.shop/partners \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"name":"PetPantry","side":"supply"}' ``` ```json { "api": "https://api.sb/petpantry.shop", "partner": { "$id": "https://api.sb/petpantry.shop/partners/partner_1", "$type": "Partner", "name": "PetPantry", "side": "supply" }, "action": { "$id": "https://api.sb/petpantry.shop/actions/action_1", "operation": "Partner.create", "status": "done" }, "links": { "self": "https://api.sb/petpantry.shop/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const partner = await $.Partner.create({ name: 'PetPantry', side: 'supply' }) ``` **CLI** ```bash npx startup-builder do Partner.create --json '{"name":"PetPantry","side":"supply"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Partner.create({ name: 'PetPantry', side: 'supply' })" } } ``` ## Example A practice-management vendor refers law firms to a court-filings API under an [Agreement](/business/nouns/agreement) for 20% of first-year revenue. It is a Partner on the distribution side. # Party URL: /business/nouns/party · Id: `noun:party` > A Party is a person or legal entity that can be a side of an Agreement or an Order, or hold rights. A Party is a person or legal entity that can be a side of an [Agreement](/business/nouns/agreement) or an [Order](/business/nouns/order), or hold rights. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `name` | `string` | Yes | The legal or personal name. | ## Object ```json { "$id": "https://api.sb/quietcopy.com/parties/party_1", "$type": "Party", "name": "QuietCopy" } ``` ## Relationships - A Party **is bound by** many [Agreements](/business/nouns/agreement): the Parties the [Agreement](/business/nouns/agreement) holds to its terms, each from the moment it signs. `boundBy`, inverse [`binds`](/business/nouns/agreement#rel-binds). - A Party **issues** many [Mandates](/business/nouns/mandate): the Party who grants a [Mandate](/business/nouns/mandate) is its principal: the [Agent](/business/nouns/agent) acts for them, and each [Action](/business/nouns/action) records them as `for`. `issues`, inverse [`issuedBy`](/business/nouns/mandate#rel-issued-by). - A Party **has** many [Referrals](/business/nouns/referral): the Party who sends a [Referral](/business/nouns/referral) earns its reward. `referrals`, inverse [`madeBy`](/business/nouns/referral#rel-made-by). - A Party **has** many [Screenings](/business/nouns/screening): a Party is screened before its first money move and again when its details change; every result stays. `screenings`, inverse [`screens`](/business/nouns/screening#rel-screens). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Dispute.answer](/business/nouns/dispute/answer) | Answer submits the seller’s Evidence on an open Dispute before its deadline: the contract, the delivered work, and its verdicts. | [Customer Lead](/agents/customer/customer-lead) | [`Dispute.answered`](/business/events/Dispute.answered) | One-way (money): `send`, `do` | | [Action.answer](/business/nouns/action/answer) | Answer gives the reply to an Action’s open Question, through any Interface, and the Action resumes. | [Party](/business/nouns/party) | [`Action.answered`](/business/events/Action.answered) | Two-way: `try`, `send`, `do` | | [Dispute.appeal](/business/nouns/dispute/appeal) | Appeal asks for one review of a decided Dispute by a Worker who took no part in the first decision. | [Billing Specialist](/agents/finance/billing-specialist) | [`Dispute.appealed`](/business/events/Dispute.appealed) | One-way (money): `send`, `do` | | [Quote.decline](/business/nouns/quote/decline) | Decline records the buyer’s refusal of a sent Quote, with the reason in their words. | [Sales Engineer](/agents/sales/sales-engineer) | [`Quote.declined`](/business/events/Quote.declined) | Two-way: `try`, `send`, `do` | | [Mandate.pause](/business/nouns/mandate/pause) | Pause stops every new Action under a Mandate at once and keeps its scope, so it can resume unchanged. | [Treasurer](/agents/finance/treasurer) | [`Mandate.paused`](/business/events/Mandate.paused) | None. | | [Agent.pause](/business/nouns/agent/pause) | Pause stops one Agent, every Agent on a Team, or every customer-facing Agent from starting new Actions in a Startup. | [Founder](/agents/founding/founder) | [`Agent.paused`](/business/events/Agent.paused) | Two-way: `try`, `send`, `do` | | [Mandate.resume](/business/nouns/mandate/resume) | Resume restarts a paused Mandate with its scope, Limits and approval rule unchanged. | [Party](/business/nouns/party) | [`Mandate.resumed`](/business/events/Mandate.resumed) | None. | | [Agent.resume](/business/nouns/agent/resume) | Resume restarts a paused Agent in every seat it holds, with its Memory, Mandates and Limits unchanged. | [Founder](/agents/founding/founder) | [`Agent.resumed`](/business/events/Agent.resumed) | Two-way: `try`, `send`, `do` | | [Agent.retire](/business/nouns/agent/retire) | Retire removes an Agent from every seat in a Startup for good and keeps its Actions, Memory and Mailbox history on the record. | [People Lead](/agents/people/people-lead) | [`Agent.retired`](/business/events/Agent.retired) | One-way (customer): `send`, `do` | | [Party.screen](/business/nouns/party/screen) | Screen checks a Party against official registers and restricted-party lists and keeps the result as a Screening. | [Risk Analyst](/agents/operations/risk-analyst) | [`Party.screened`](/business/events/Party.screened) | Two-way: `try`, `send`, `do` | | [Problem.suggest](/business/nouns/problem/suggest) | Suggest records a Customer’s ask for something the Product lacks as Evidence on a Problem, with the asker attached. | [Party](/business/nouns/party) | [`Problem.suggested`](/business/events/Problem.suggested) | Two-way: `try`, `send`, `do` | | [Agreement.terminate](/business/nouns/agreement/terminate) | Terminate ends an Agreement under its own term, records the reason and the date, and keeps the signed record. | [Legal Lead](/agents/legal/legal-lead) | [`Agreement.terminated`](/business/events/Agreement.terminated) | One-way (money, customer): `send`, `do` | | [Role.vacate](/business/nouns/role/vacate) | Vacate takes the Worker out of a Role, and the seat’s Tasks route to the Role it escalates to until a new Worker is staffed. | [People Lead](/agents/people/people-lead) | [`Role.vacated`](/business/events/Role.vacated) | Two-way: `try`, `send`, `do` | | [Party.create](/business/nouns/party/create) | Creates a Party. Inherited from [Noun](/business/nouns/noun). | None. | `Party.created` | Two-way: `try`, `send`, `do` | | [Party.get](/business/nouns/party/get) | Returns one Party by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Party.list](/business/nouns/party/list) | Returns Parties, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Party.update](/business/nouns/party/update) | Changes the given properties of a Party. Inherited from [Noun](/business/nouns/noun). | None. | `Party.updated` | Two-way: `try`, `send`, `do` | | [Party.delete](/business/nouns/party/delete) | Deletes a Party; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Party.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Party.create` | Yes | Yes | Yes | No | | `Party.get` | Yes | Yes | Yes | Yes | | `Party.list` | Yes | Yes | Yes | Yes | | `Party.update` | Yes | Yes | Yes | No | | `Party.delete` | Yes | Yes | Yes | No | | `Party.screen` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Screen the latest party. ``` **API** ```bash curl -X POST https://api.sb/quietcopy.com/parties/party_1/screen \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/quietcopy.com", "screening": { "$id": "https://api.sb/quietcopy.com/screenings/screening_1", "$type": "Screening", "lists": {}, "outcome": "clear", "via": "platform" }, "party": { "$id": "https://api.sb/quietcopy.com/parties/party_1", "$type": "Party", "name": "QuietCopy" }, "action": { "$id": "https://api.sb/quietcopy.com/actions/action_1", "operation": "Party.screen", "status": "done" }, "links": { "self": "https://api.sb/quietcopy.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { screening, party } = await $.Party.screen({ party: 'party_1' }) ``` **CLI** ```bash npx startup-builder do Party.screen --json '{"party":"party_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Party.screen({ party: 'party_1' })" } } ``` ## Example A game studio orders a voice-over through a marketplace, so the studio is a Party to the [Order](/business/nouns/order). The producer who signs the usage [Agreement](/business/nouns/agreement) is a Party to it. # screen URL: /business/nouns/party/screen · Id: `verb:Party.screen` · Call: `await $.Party.screen({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Screen checks a Party against official registers and restricted-party lists and keeps the result as a Screening. Screen checks a [Party](/business/nouns/party) against official registers and restricted-party lists and keeps the result as a [Screening](/business/nouns/screening). ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `party` | [Party](/business/nouns/party) | Yes | The Party to check: a Customer, Supplier, Partner or the Company’s own owners. | | `markets` | list of [Market](/business/nouns/market) | No | The Markets whose lists apply. Defaults to the Party’s and the Startup’s Markets. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `screening` | [Screening](/business/nouns/screening) | Yes | The Screening, with the lists checked, their versions, any matches and the outcome. | | `party` | [Party](/business/nouns/party) | Yes | The Party screened. | ## Effects - Emits [`Party.screened`](/business/events/Party.screened). - Performed by the [Risk Analyst](/agents/operations/risk-analyst). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Runs before the Party’s first money move and again when its details change. - A `match` holds the Party’s pending Orders and opens an Approval with the match attached. - Records Stripe’s own verification result as a Screening with `via: stripe` on the same Party. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Party.screen](/business/nouns/party/screen) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Screen the latest party. ``` **API** ```bash curl -X POST https://api.sb/quietcopy.com/parties/party_1/screen \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/quietcopy.com", "screening": { "$id": "https://api.sb/quietcopy.com/screenings/screening_1", "$type": "Screening", "lists": {}, "outcome": "clear", "via": "platform" }, "party": { "$id": "https://api.sb/quietcopy.com/parties/party_1", "$type": "Party", "name": "QuietCopy" }, "action": { "$id": "https://api.sb/quietcopy.com/actions/action_1", "operation": "Party.screen", "status": "done" }, "links": { "self": "https://api.sb/quietcopy.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { screening, party } = await $.Party.screen({ party: 'party_1' }) ``` **CLI** ```bash npx startup-builder do Party.screen --json '{"party":"party_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Party.screen({ party: 'party_1' })" } } ``` # approve URL: /business/nouns/pay-run/approve · Id: `verb:PayRun.approve` · Call: `await $.PayRun.approve({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Approve accepts a prepared Pay Run within the approver’s Mandate, books its cost, and schedules payment to land on the pay date. Approve accepts a prepared [Pay Run](/business/nouns/pay-run) within the approver’s [Mandate](/business/nouns/mandate), books its cost, and schedules payment to land on the pay date. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `payRun` | [Pay Run](/business/nouns/pay-run) | Yes | The prepared Pay Run. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `payRun` | [Pay Run](/business/nouns/pay-run) | Yes | The approved Pay Run, scheduled for its pay date. | ## Effects - Emits [`PayRun.approved`](/business/events/PayRun.approved). - Performed by the [Payroll Specialist](/agents/people/payroll-specialist). - One-way (money): it waits out its delay window, and runs in the `send` and `do` modes. - Above the Payroll Specialist’s Limit, waits for an Approval from the Founder. - Schedules `PayRun.pay` early enough for the money to land on the pay date. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [PayRun.approve](/business/nouns/pay-run/approve) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Medium: one-way, bounded (money) | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | 1 business hour, in which a watcher can pause, redirect or cancel it; then it runs. | | Limit | The spend [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) or [Mandate](/business/nouns/mandate) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Approve the latest pay run. ``` **API** ```bash curl -X POST https://api.sb/kilnbakery.com/pay-runs/pay_run_1/approve \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/kilnbakery.com", "payRun": { "$id": "https://api.sb/kilnbakery.com/pay-runs/pay_run_1", "$type": "PayRun", "company": "company_1", "periodStart": "2026-10-22", "periodEnd": "2026-10-22", "payDate": "2026-10-22" }, "action": { "$id": "https://api.sb/kilnbakery.com/actions/action_1", "operation": "PayRun.approve", "status": "done" }, "links": { "self": "https://api.sb/kilnbakery.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const payRun = await $.PayRun.approve({ payRun: 'pay_run_1' }) ``` **CLI** ```bash npx startup-builder do PayRun.approve --json '{"payRun":"pay_run_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.PayRun.approve({ payRun: 'pay_run_1' })" } } ``` Guides that call it: [Run payroll](/systems/people/run-payroll). # Pay Run URL: /business/nouns/pay-run · Id: `noun:pay-run` > A Pay Run is one pay period’s payroll for a Company: each employee’s gross pay, withholding, deductions and net pay, approved and paid together. A Pay Run is one pay period’s payroll for a [Company](/business/nouns/company): each employee’s gross pay, withholding, deductions and net pay, approved and paid together. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `company` | [Company](/business/nouns/company) | Yes | The employer of record for everyone it pays. | | `periodStart` | `date` | Yes | The first day of the pay period. | | `periodEnd` | `date` | Yes | The last day of the pay period. | | `payDate` | `date` | Yes | The day net pay reaches each employee’s bank. | | `kind` | `string` | Yes | A `regular` run on the pay schedule, or an `offCycle` run for a bonus, a correction or final pay. | | `humans` | list of [Human](/business/nouns/human) | No | The employees it pays. | | `gross` | `money` | No | Pay before withholding and deductions, for everyone in the run. | | `withheld` | `money` | No | Income and payroll taxes withheld from employees’ pay. | | `deductions` | `money` | No | Benefit and retirement deductions the employees elected. | | `employerTax` | `money` | No | Payroll taxes the Company owes on top of gross pay. | | `net` | `money` | No | What reaches the employees’ banks: gross less withholding and deductions. | | `status` | `string` | Yes | Where the Pay Run stands; only an `approved` run is paid. | ## Object ```json { "$id": "https://api.sb/kilnbakery.com/pay-runs/pay_run_1", "$type": "PayRun", "company": "company_1", "periodStart": "2026-10-22", "periodEnd": "2026-10-22", "payDate": "2026-10-22", "kind": "regular", "humans": [ "human_1" ], "gross": { "amount": 9, "currency": "USD" }, "withheld": { "amount": 9, "currency": "USD" }, "deductions": { "amount": 9, "currency": "USD" }, "employerTax": { "amount": 9, "currency": "USD" }, "net": { "amount": 9, "currency": "USD" }, "status": "prepared" } ``` ## Relationships - A Pay Run **is paid by** one [Company](/business/nouns/company): a Pay Run is paid by one [Company](/business/nouns/company), the employer of record for everyone in it. `paidBy`, inverse [`payRuns`](/business/nouns/company#rel-pay-runs). - A Pay Run **pays** many [Humans](/business/nouns/human): a Pay Run pays the [Humans](/business/nouns/human) the [Company](/business/nouns/company) employs; each employee appears in one run per pay period. `pays`, inverse [`paidIn`](/business/nouns/human#rel-paid-in). ## Lifecycle | State | Meaning | Moves to | | --- | --- | --- | | `prepared` (first) | Every amount is computed and the run waits for approval; nothing is booked or paid. | `approved` by [PayRun.approve](/business/nouns/pay-run/approve); `voided` by [PayRun.void](/business/nouns/pay-run/void) | | `approved` | The cost is booked and payment is scheduled to land on the pay date. | `paid` by [PayRun.pay](/business/nouns/pay-run/pay) | | `paid` | Net pay reached each employee, and the payroll provider holds the taxes and deductions to remit. | None: it ends here. | | `voided` | The run was set aside before approval; nothing was booked or paid, and the record stays. | None: it ends here. | ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [PayRun.approve](/business/nouns/pay-run/approve) | Approve accepts a prepared Pay Run within the approver’s Mandate, books its cost, and schedules payment to land on the pay date. | [Payroll Specialist](/agents/people/payroll-specialist) | [`PayRun.approved`](/business/events/PayRun.approved) | One-way (money): `send`, `do` | | [PayRun.pay](/business/nouns/pay-run/pay) | Pay funds an approved Pay Run: net pay to each employee’s bank on the pay date, taxes and deductions to the payroll provider. | [Treasurer](/agents/finance/treasurer) | [`PayRun.paid`](/business/events/PayRun.paid) | One-way (money): `send`, `do` | | [PayRun.prepare](/business/nouns/pay-run/prepare) | Prepare computes one pay period’s gross pay, withholding, deductions and employer taxes for each employee, and holds the Pay Run for approval. | [Payroll Specialist](/agents/people/payroll-specialist) | [`PayRun.prepared`](/business/events/PayRun.prepared) | Two-way: `try`, `send`, `do` | | [PayRun.void](/business/nouns/pay-run/void) | Void sets aside a prepared Pay Run that is wrong, so a corrected one can be prepared; the record stays. | [Payroll Specialist](/agents/people/payroll-specialist) | [`PayRun.voided`](/business/events/PayRun.voided) | Two-way: `try`, `send`, `do` | | [PayRun.get](/business/nouns/pay-run/get) | Returns one Pay Run by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [PayRun.list](/business/nouns/pay-run/list) | Returns Pay Runs, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | A Pay Run is kept forever and never edited: it has no `update` or `delete`. ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `PayRun.get` | Yes | Yes | Yes | Yes | | `PayRun.list` | Yes | Yes | Yes | Yes | | `PayRun.approve` | Yes | No | No | No | | `PayRun.pay` | Yes | No | No | No | | `PayRun.prepare` | Yes | Yes | Yes | No | | `PayRun.void` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Prepare the latest pay run with a company. ``` **API** ```bash curl -X POST https://api.sb/tutorloop.com/pay-runs/prepare \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"company":"company_1","periodStart":"2026-10-22","periodEnd":"2026-10-22","payDate":"2026-10-22"}' ``` ```json { "api": "https://api.sb/tutorloop.com", "payRun": { "$id": "https://api.sb/tutorloop.com/pay-runs/pay_run_1", "$type": "PayRun", "company": "company_1", "periodStart": "2026-10-22", "periodEnd": "2026-10-22", "payDate": "2026-10-22" }, "action": { "$id": "https://api.sb/tutorloop.com/actions/action_1", "operation": "PayRun.prepare", "status": "done" }, "links": { "self": "https://api.sb/tutorloop.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const payRun = await $.PayRun.prepare({ company: 'company_1', periodStart: '2026-10-22', periodEnd: '2026-10-22', payDate: '2026-10-22' }) ``` **CLI** ```bash npx startup-builder do PayRun.prepare --json '{"company":"company_1","periodStart":"2026-10-22","periodEnd":"2026-10-22","payDate":"2026-10-22"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.PayRun.prepare({ company: 'company_1', periodStart: '2026-10-22', periodEnd: '2026-10-22', payDate: '2026-10-22' })" } } ``` ## Example A property-management app with four employees in two states pays on the 15th and the last day of each month. The [Payroll Specialist](/agents/people/payroll-specialist) prepares the run for the 1st to the 15th: $18,400 gross, withholding for both states, $14,050 net. It approves within its [Limit](/business/nouns/limit), and the [Treasurer](/agents/finance/treasurer) funds it two days before payday. # pay URL: /business/nouns/pay-run/pay · Id: `verb:PayRun.pay` · Call: `await $.PayRun.pay({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Pay funds an approved Pay Run: net pay to each employee’s bank on the pay date, taxes and deductions to the payroll provider. Pay funds an approved [Pay Run](/business/nouns/pay-run): net pay to each employee’s bank on the pay date, taxes and deductions to the payroll provider. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `payRun` | [Pay Run](/business/nouns/pay-run) | Yes | The approved Pay Run. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `payRun` | [Pay Run](/business/nouns/pay-run) | Yes | The paid Pay Run. | | `transaction` | [Transaction](/business/nouns/transaction) | Yes | The funding Transaction. | ## Effects - Emits [`PayRun.paid`](/business/events/PayRun.paid). - Performed by the [Treasurer](/agents/finance/treasurer). - One-way (money): it waits out its delay window, and runs in the `send` and `do` modes. - Pays from the operating account, so the money must be there before the pay date. - The payroll provider remits each withholding and files each employer return by its deadline. - A deposit the bank returns arrives as a failed Transaction and opens a Task to pay that employee off-cycle. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [PayRun.pay](/business/nouns/pay-run/pay) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Medium: one-way, bounded (money) | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | 1 business hour, in which a watcher can pause, redirect or cancel it; then it runs. | | Limit | The spend [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) or [Mandate](/business/nouns/mandate) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Pay the latest pay run. ``` **API** ```bash curl -X POST https://api.sb/shiftnote.app/pay-runs/pay_run_1/pay \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/shiftnote.app", "payRun": { "$id": "https://api.sb/shiftnote.app/pay-runs/pay_run_1", "$type": "PayRun", "company": "company_1", "periodStart": "2026-10-22", "periodEnd": "2026-10-22", "payDate": "2026-10-22" }, "transaction": { "$id": "https://api.sb/shiftnote.app/transactions/transaction_1", "$type": "Transaction", "kind": "charge", "amount": { "amount": 79, "currency": "USD" } }, "action": { "$id": "https://api.sb/shiftnote.app/actions/action_1", "operation": "PayRun.pay", "status": "done" }, "links": { "self": "https://api.sb/shiftnote.app/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { payRun, transaction } = await $.PayRun.pay({ payRun: 'pay_run_1' }) ``` **CLI** ```bash npx startup-builder do PayRun.pay --json '{"payRun":"pay_run_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.PayRun.pay({ payRun: 'pay_run_1' })" } } ``` # prepare URL: /business/nouns/pay-run/prepare · Id: `verb:PayRun.prepare` · Call: `await $.PayRun.prepare({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Prepare computes one pay period’s gross pay, withholding, deductions and employer taxes for each employee, and holds the Pay Run for approval. Prepare computes one pay period’s gross pay, withholding, deductions and employer taxes for each employee, and holds the [Pay Run](/business/nouns/pay-run) for approval. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `company` | [Company](/business/nouns/company) | Yes | The employer Company. | | `periodStart` | `date` | Yes | The first day of the pay period. | | `periodEnd` | `date` | Yes | The last day of the pay period. | | `payDate` | `date` | Yes | The day net pay should land. | | `kind` | `string` | No | Defaults to `regular`; `offCycle` pays outside the schedule. | | `humans` | list of [Human](/business/nouns/human) | No | Only these employees. Defaults to every employee of the Company. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `payRun` | [Pay Run](/business/nouns/pay-run) | Yes | The prepared Pay Run, with every amount per employee. | ## Effects - Emits [`PayRun.prepared`](/business/events/PayRun.prepared). - Performed by the [Payroll Specialist](/agents/people/payroll-specialist). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Reads each employee’s pay rate from their employment Agreement and withholds for the state where they work. - Adds the Benefits deductions each employee elected. - Opens a Task for the Payroll Specialist when a rate, a tax setup or a bank account is missing. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [PayRun.prepare](/business/nouns/pay-run/prepare) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Prepare the latest pay run with a company. ``` **API** ```bash curl -X POST https://api.sb/tutorloop.com/pay-runs/prepare \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"company":"company_1","periodStart":"2026-10-22","periodEnd":"2026-10-22","payDate":"2026-10-22"}' ``` ```json { "api": "https://api.sb/tutorloop.com", "payRun": { "$id": "https://api.sb/tutorloop.com/pay-runs/pay_run_1", "$type": "PayRun", "company": "company_1", "periodStart": "2026-10-22", "periodEnd": "2026-10-22", "payDate": "2026-10-22" }, "action": { "$id": "https://api.sb/tutorloop.com/actions/action_1", "operation": "PayRun.prepare", "status": "done" }, "links": { "self": "https://api.sb/tutorloop.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const payRun = await $.PayRun.prepare({ company: 'company_1', periodStart: '2026-10-22', periodEnd: '2026-10-22', payDate: '2026-10-22' }) ``` **CLI** ```bash npx startup-builder do PayRun.prepare --json '{"company":"company_1","periodStart":"2026-10-22","periodEnd":"2026-10-22","payDate":"2026-10-22"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.PayRun.prepare({ company: 'company_1', periodStart: '2026-10-22', periodEnd: '2026-10-22', payDate: '2026-10-22' })" } } ``` Next: [`PayRun.approve`](/business/nouns/pay-run/approve) (in `guide:run-payroll`). Guides that call it: [Run payroll](/systems/people/run-payroll). # void URL: /business/nouns/pay-run/void · Id: `verb:PayRun.void` · Call: `await $.PayRun.void({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Void sets aside a prepared Pay Run that is wrong, so a corrected one can be prepared; the record stays. Void sets aside a prepared [Pay Run](/business/nouns/pay-run) that is wrong, so a corrected one can be prepared; the record stays. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `payRun` | [Pay Run](/business/nouns/pay-run) | Yes | The prepared Pay Run. | | `reason` | `text` | Yes | Why it was set aside. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `payRun` | [Pay Run](/business/nouns/pay-run) | Yes | The voided Pay Run. | ## Effects - Emits [`PayRun.voided`](/business/events/PayRun.voided). - Performed by the [Payroll Specialist](/agents/people/payroll-specialist). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - An approved Pay Run cannot be voided; a mistake in it is corrected in the next run. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [PayRun.void](/business/nouns/pay-run/void) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Void the latest pay run. ``` **API** ```bash curl -X POST https://api.sb/ledgerlark.com/pay-runs/pay_run_1/void \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"reason":"Example reason"}' ``` ```json { "api": "https://api.sb/ledgerlark.com", "payRun": { "$id": "https://api.sb/ledgerlark.com/pay-runs/pay_run_1", "$type": "PayRun", "company": "company_1", "periodStart": "2026-10-22", "periodEnd": "2026-10-22", "payDate": "2026-10-22" }, "action": { "$id": "https://api.sb/ledgerlark.com/actions/action_1", "operation": "PayRun.void", "status": "done" }, "links": { "self": "https://api.sb/ledgerlark.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const payRun = await $.PayRun.void({ payRun: 'pay_run_1', reason: 'Example reason' }) ``` **CLI** ```bash npx startup-builder do PayRun.void --json '{"payRun":"pay_run_1","reason":"Example reason"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.PayRun.void({ payRun: 'pay_run_1', reason: 'Example reason' })" } } ``` # add URL: /business/nouns/payment-source/add · Id: `verb:PaymentSource.add` · Call: `await $.PaymentSource.add({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Add saves a new Payment Source for a Customer through Stripe’s embedded form on the Startup’s Domain, and can make it the default. Add saves a new [Payment Source](/business/nouns/payment-source) for a [Customer](/business/nouns/customer) through Stripe’s embedded form on the [Startup](/business/nouns/startup)’s [Domain](/business/nouns/domain), and can make it the default. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `customer` | [Customer](/business/nouns/customer) | Yes | The Customer who saves it. | | `kind` | `string` | Yes | How it pays; the form offers only the kinds the Customer’s Market accepts. | | `default` | `boolean` | No | True to charge it for every new Invoice and renewal. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `paymentSource` | [Payment Source](/business/nouns/payment-source) | Yes | The saved Payment Source; Stripe holds its details. | ## Effects - Emits [`PaymentSource.added`](/business/events/PaymentSource.added). - Performed by the [Billing Specialist](/agents/finance/billing-specialist). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Collects the details in Stripe’s embedded form, so the Startup never holds a card or account number. - As the new default, charges each open `charge` Invoice that failed at once, ahead of the next dunning retry. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [PaymentSource.add](/business/nouns/payment-source/add) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Add the latest payment source with a customer. ``` **API** ```bash curl -X POST https://api.sb/petpantry.shop/payment-sources/add \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"customer":"customer_1","kind":"card"}' ``` ```json { "api": "https://api.sb/petpantry.shop", "paymentSource": { "$id": "https://api.sb/petpantry.shop/payment-sources/payment_source_1", "$type": "PaymentSource", "kind": "card", "label": "Visa 4242" }, "action": { "$id": "https://api.sb/petpantry.shop/actions/action_1", "operation": "PaymentSource.add", "status": "done" }, "links": { "self": "https://api.sb/petpantry.shop/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const paymentSource = await $.PaymentSource.add({ customer: 'customer_1', kind: 'card' }) ``` **CLI** ```bash npx startup-builder do PaymentSource.add --json '{"customer":"customer_1","kind":"card"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.PaymentSource.add({ customer: 'customer_1', kind: 'card' })" } } ``` # Payment Source URL: /business/nouns/payment-source · Id: `noun:payment-source` > A Payment Source is a card, bank debit or wallet a Customer saves with a Startup, held at Stripe and charged for Orders and Invoices. A Payment Source is a card, bank debit or wallet a [Customer](/business/nouns/customer) saves with a [Startup](/business/nouns/startup), held at Stripe and charged for [Orders](/business/nouns/order) and [Invoices](/business/nouns/invoice). ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `kind` | `string` | Yes | How it pays: a card, a bank debit from the Customer’s account, or a wallet on the Customer’s phone or browser. | | `label` | `string` | Yes | What the Customer sees, such as the card brand and last four digits; never the full number. | | `expiresOn` | `date` | No | When a card expires; the billing portal asks for a new one 30 days before. | | `default` | `boolean` | No | True for the one Payment Source that new Invoices and renewals charge. | | `removedAt` | `datetime` | No | When the Customer removed it; nothing charges it after, and the record stays. | ## Object ```json { "$id": "https://api.sb/kilnbakery.com/payment-sources/payment_source_1", "$type": "PaymentSource", "kind": "card", "label": "Visa 4242", "expiresOn": "2026-10-22", "default": true, "removedAt": "2026-10-22T12:00:00Z" } ``` ## Relationships - A Payment Source **is saved by** one [Customer](/business/nouns/customer): a [Customer](/business/nouns/customer) saves the Payment Sources its [Orders](/business/nouns/order), [Subscriptions](/business/nouns/subscription) and [Invoices](/business/nouns/invoice) charge; each belongs to one [Startup](/business/nouns/startup) and never moves to a sibling. `savedBy`, inverse [`saves`](/business/nouns/customer#rel-saves). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [PaymentSource.add](/business/nouns/payment-source/add) | Add saves a new Payment Source for a Customer through Stripe’s embedded form on the Startup’s Domain, and can make it the default. | [Billing Specialist](/agents/finance/billing-specialist) | [`PaymentSource.added`](/business/events/PaymentSource.added) | Two-way: `try`, `send`, `do` | | [PaymentSource.remove](/business/nouns/payment-source/remove) | Remove detaches a saved Payment Source so nothing charges it again, and keeps the record. | [Billing Specialist](/agents/finance/billing-specialist) | [`PaymentSource.removed`](/business/events/PaymentSource.removed) | Two-way: `try`, `send`, `do` | | [PaymentSource.get](/business/nouns/payment-source/get) | Returns one Payment Source by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [PaymentSource.list](/business/nouns/payment-source/list) | Returns Payment Sources, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [PaymentSource.update](/business/nouns/payment-source/update) | Changes the given properties of a Payment Source. Inherited from [Noun](/business/nouns/noun). | None. | `PaymentSource.updated` | Two-way: `try`, `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `PaymentSource.get` | Yes | Yes | Yes | Yes | | `PaymentSource.list` | Yes | Yes | Yes | Yes | | `PaymentSource.update` | Yes | Yes | Yes | No | | `PaymentSource.add` | Yes | Yes | Yes | No | | `PaymentSource.remove` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Add the latest payment source with a customer. ``` **API** ```bash curl -X POST https://api.sb/petpantry.shop/payment-sources/add \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"customer":"customer_1","kind":"card"}' ``` ```json { "api": "https://api.sb/petpantry.shop", "paymentSource": { "$id": "https://api.sb/petpantry.shop/payment-sources/payment_source_1", "$type": "PaymentSource", "kind": "card", "label": "Visa 4242" }, "action": { "$id": "https://api.sb/petpantry.shop/actions/action_1", "operation": "PaymentSource.add", "status": "done" }, "links": { "self": "https://api.sb/petpantry.shop/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const paymentSource = await $.PaymentSource.add({ customer: 'customer_1', kind: 'card' }) ``` **CLI** ```bash npx startup-builder do PaymentSource.add --json '{"customer":"customer_1","kind":"card"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.PaymentSource.add({ customer: 'customer_1', kind: 'card' })" } } ``` ## Example A clinic on shiftnote.app saves a card ending 4242 as its default Payment Source and a bank debit as a backup. When the card expires, its renewal fails, and adding a new card in the [Portal](/business/nouns/portal) pays the open [Invoice](/business/nouns/invoice) at once. # remove URL: /business/nouns/payment-source/remove · Id: `verb:PaymentSource.remove` · Call: `await $.PaymentSource.remove({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Remove detaches a saved Payment Source so nothing charges it again, and keeps the record. Remove detaches a saved [Payment Source](/business/nouns/payment-source) so nothing charges it again, and keeps the record. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `paymentSource` | [Payment Source](/business/nouns/payment-source) | Yes | The saved Payment Source. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `paymentSource` | [Payment Source](/business/nouns/payment-source) | Yes | The removed Payment Source, kept on record. | ## Effects - Emits [`PaymentSource.removed`](/business/events/PaymentSource.removed). - Performed by the [Billing Specialist](/agents/finance/billing-specialist). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - When it was the default, the most recently added remaining Payment Source becomes the default. - With none left, the next `charge` Invoice fails into dunning, and the Customer is asked to add one. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [PaymentSource.remove](/business/nouns/payment-source/remove) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Remove the latest payment source. ``` **API** ```bash curl -X POST https://api.sb/ledgerlark.com/payment-sources/payment_source_1/remove \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/ledgerlark.com", "paymentSource": { "$id": "https://api.sb/ledgerlark.com/payment-sources/payment_source_1", "$type": "PaymentSource", "kind": "card", "label": "Visa 4242" }, "action": { "$id": "https://api.sb/ledgerlark.com/actions/action_1", "operation": "PaymentSource.remove", "status": "done" }, "links": { "self": "https://api.sb/ledgerlark.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const paymentSource = await $.PaymentSource.remove({ paymentSource: 'payment_source_1' }) ``` **CLI** ```bash npx startup-builder do PaymentSource.remove --json '{"paymentSource":"payment_source_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.PaymentSource.remove({ paymentSource: 'payment_source_1' })" } } ``` # close URL: /business/nouns/period/close · Id: `verb:Period.close` · Call: `await $.Period.close({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Close ends a month’s books once every Entry in the Period is reconciled, and makes its statements final. Close ends a month’s books once every [Entry](/business/nouns/entry) in the [Period](/business/nouns/period) is reconciled, and makes its statements final. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `period` | [Period](/business/nouns/period) | Yes | The open Period. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `period` | [Period](/business/nouns/period) | Yes | The closed Period. | ## Effects - Emits [`Period.closed`](/business/events/Period.closed). - Performed by the [Finance Lead](/agents/finance/finance-lead). - Two-way: it runs at once, in the `try`, `send` and `do` modes. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Period.close](/business/nouns/period/close) | | The record is not in a state that allows this Verb, so the call is refused. | [`refused`](/code/api/errors/refused) | Read the record, run the Verb that moves it to an allowed state, then retry. | [Period.close](/business/nouns/period/close) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Close the latest period. ``` **API** ```bash curl -X POST https://api.sb/ledgerlark.com/periods/period_1/close \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/ledgerlark.com", "period": { "$id": "https://api.sb/ledgerlark.com/periods/period_1", "$type": "Period", "month": "2026-10-22", "status": "Closed" }, "action": { "$id": "https://api.sb/ledgerlark.com/actions/action_1", "operation": "Period.close", "status": "done" }, "links": { "self": "https://api.sb/ledgerlark.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const period = await $.Period.close({ period: 'period_1' }) ``` **CLI** ```bash npx startup-builder do Period.close --json '{"period":"period_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Period.close({ period: 'period_1' })" } } ``` # Period URL: /business/nouns/period · Id: `noun:period` > A Period is one month of a Startup’s books, open until every Transaction reconciles, then closed and locked. A Period is one month of a [Startup](/business/nouns/startup)’s books, open until every [Transaction](/business/nouns/transaction) reconciles, then closed and locked. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `month` | `date` | Yes | The first day of the month it covers. | | `status` | `string` | Yes | One of `Open`, `Closed`, or `Locked`. | ## Object ```json { "$id": "https://api.sb/routewise.dev/periods/period_1", "$type": "Period", "month": "2026-10-22", "status": "Open" } ``` ## Relationships - A Period **has** many [Budgets](/business/nouns/budget): a [Budget](/business/nouns/budget) plans one Period, read beside the actual [Entries](/business/nouns/entry) that fall in it. `budgets`, inverse [`plans`](/business/nouns/budget#rel-plans). - A Period **has** many [Entries](/business/nouns/entry): an [Entry](/business/nouns/entry) posts to the month its [Event](/business/nouns/event) happened; closing the Period locks it. `entries`, inverse [`fallsIn`](/business/nouns/entry#rel-falls-in). - A Period **has** many [Statements](/business/nouns/statement): a [Statement](/business/nouns/statement) reports one Period; each closed Period carries its P&L, balance sheet and cash flow. `statements`, inverse [`reports`](/business/nouns/statement#rel-reports). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Period.close](/business/nouns/period/close) | Close ends a month’s books once every Entry in the Period is reconciled, and makes its statements final. | [Finance Lead](/agents/finance/finance-lead) | [`Period.closed`](/business/events/Period.closed) | Two-way: `try`, `send`, `do` | | [Period.lock](/business/nouns/period/lock) | Lock seals a closed Period, so any later correction posts to the next open Period. | [Finance Lead](/agents/finance/finance-lead) | [`Period.locked`](/business/events/Period.locked) | One-way (money): `send`, `do` | | [Period.recognize](/business/nouns/period/recognize) | Recognize moves the revenue a Period earned out of deferred revenue, by the Startup’s revenue-recognition Policy. | [Finance Lead](/agents/finance/finance-lead) | [`Period.recognized`](/business/events/Period.recognized) | Two-way: `try`, `send`, `do` | | [Period.get](/business/nouns/period/get) | Returns one Period by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Period.list](/business/nouns/period/list) | Returns Periods, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Period.update](/business/nouns/period/update) | Changes the given properties of a Period. Inherited from [Noun](/business/nouns/noun). | None. | `Period.updated` | Two-way: `try`, `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Period.get` | Yes | Yes | Yes | Yes | | `Period.list` | Yes | Yes | Yes | Yes | | `Period.update` | Yes | Yes | Yes | No | | `Period.close` | Yes | Yes | Yes | No | | `Period.lock` | Yes | No | No | No | | `Period.recognize` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Close the latest period. ``` **API** ```bash curl -X POST https://api.sb/ledgerlark.com/periods/period_1/close \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/ledgerlark.com", "period": { "$id": "https://api.sb/ledgerlark.com/periods/period_1", "$type": "Period", "month": "2026-10-22", "status": "Closed" }, "action": { "$id": "https://api.sb/ledgerlark.com/actions/action_1", "operation": "Period.close", "status": "done" }, "links": { "self": "https://api.sb/ledgerlark.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const period = await $.Period.close({ period: 'period_1' }) ``` **CLI** ```bash npx startup-builder do Period.close --json '{"period":"period_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Period.close({ period: 'period_1' })" } } ``` ## Example Period `2026-03` of a tutoring marketplace's books closes on the third working day, once 1,840 [Transactions](/business/nouns/transaction) reconcile. Then it locks, and no [Entry](/business/nouns/entry) in it changes. # lock URL: /business/nouns/period/lock · Id: `verb:Period.lock` · Call: `await $.Period.lock({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Lock seals a closed Period, so any later correction posts to the next open Period. Lock seals a closed [Period](/business/nouns/period), so any later correction posts to the next open Period. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `period` | [Period](/business/nouns/period) | Yes | The closed Period. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `period` | [Period](/business/nouns/period) | Yes | The locked Period. | ## Effects - Emits [`Period.locked`](/business/events/Period.locked). - Performed by the [Finance Lead](/agents/finance/finance-lead). - One-way (money): it waits out its delay window, and runs in the `send` and `do` modes. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Period.lock](/business/nouns/period/lock) | | The record is not in a state that allows this Verb, so the call is refused. | [`refused`](/code/api/errors/refused) | Read the record, run the Verb that moves it to an allowed state, then retry. | [Period.lock](/business/nouns/period/lock) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Medium: one-way, bounded (money) | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | 1 business hour, in which a watcher can pause, redirect or cancel it; then it runs. | | Limit | The spend [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) or [Mandate](/business/nouns/mandate) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Lock the latest period. ``` **API** ```bash curl -X POST https://api.sb/kilnbakery.com/periods/period_1/lock \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/kilnbakery.com", "period": { "$id": "https://api.sb/kilnbakery.com/periods/period_1", "$type": "Period", "month": "2026-10-22", "status": "Locked" }, "action": { "$id": "https://api.sb/kilnbakery.com/actions/action_1", "operation": "Period.lock", "status": "done" }, "links": { "self": "https://api.sb/kilnbakery.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const period = await $.Period.lock({ period: 'period_1' }) ``` **CLI** ```bash npx startup-builder do Period.lock --json '{"period":"period_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Period.lock({ period: 'period_1' })" } } ``` # recognize URL: /business/nouns/period/recognize · Id: `verb:Period.recognize` · Call: `await $.Period.recognize({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Recognize moves the revenue a Period earned out of deferred revenue, by the Startup’s revenue-recognition Policy. Recognize moves the revenue a [Period](/business/nouns/period) earned out of deferred revenue, by the [Startup](/business/nouns/startup)’s revenue-recognition [Policy](/business/nouns/policy). ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `period` | [Period](/business/nouns/period) | Yes | The open Period to recognize. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `entries` | list of [Entry](/business/nouns/entry) | Yes | The recognition Entries it posted. | | `period` | [Period](/business/nouns/period) | Yes | The Period whose revenue was recognized. | ## Effects - Emits [`Period.recognized`](/business/events/Period.recognized). - Performed by the [Finance Lead](/agents/finance/finance-lead). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Runs daily, and once more before the Period closes. - Recognizes a Subscription by elapsed days and an Order on delivery. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Period.recognize](/business/nouns/period/recognize) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Recognize the latest period. ``` **API** ```bash curl -X POST https://api.sb/ledgerlark.com/periods/period_1/recognize \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/ledgerlark.com", "entries": [ { "$id": "https://api.sb/ledgerlark.com/entries/entry_1", "$type": "Entry", "account": "cash", "amount": { "amount": 400, "currency": "USD" }, "direction": "debit", "startup": "startup_1" } ], "period": { "$id": "https://api.sb/ledgerlark.com/periods/period_1", "$type": "Period", "month": "2026-10-22", "status": "Open" }, "action": { "$id": "https://api.sb/ledgerlark.com/actions/action_1", "operation": "Period.recognize", "status": "done" }, "links": { "self": "https://api.sb/ledgerlark.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { entries, period } = await $.Period.recognize({ period: 'period_1' }) ``` **CLI** ```bash npx startup-builder do Period.recognize --json '{"period":"period_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Period.recognize({ period: 'period_1' })" } } ``` # Permission URL: /business/nouns/permission · Id: `noun:permission` > A Permission is what a Role may do: a Verb on a Noun within a scope, optionally bounded by a Limit. A Permission is what a [Role](/business/nouns/role) may do: a [Verb](/business/nouns/verb) on a [Noun](/business/nouns/noun) within a scope, optionally bounded by a [Limit](/business/nouns/limit). ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `scope` | `string` | Yes | Where it applies, such as a Startup or a Tenant. | | `limit` | [Limit](/business/nouns/limit) | No | The Limit that bounds it. | ## Object ```json { "$id": "https://api.sb/ledgerlark.com/permissions/permission_1", "$type": "Permission", "scope": "Example scope", "limit": "limit_1" } ``` ## Relationships - A Permission **allows** one [Verb](/business/nouns/verb): each Permission allows one [Verb](/business/nouns/verb), within its scope and [Limit](/business/nouns/limit). `allows`, inverse [`allowedBy`](/business/nouns/verb#rel-allowed-by). - A Permission **is held by** one [Role](/business/nouns/role): a [Role](/business/nouns/role)’s Permissions are what its [Worker](/business/nouns/worker) may do: [Verbs](/business/nouns/verb) on [Nouns](/business/nouns/noun) within a scope and a [Limit](/business/nouns/limit). `heldBy`, inverse [`holds`](/business/nouns/role#rel-holds). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Permission.create](/business/nouns/permission/create) | Creates a Permission. Inherited from [Noun](/business/nouns/noun). | None. | `Permission.created` | Two-way: `try`, `send`, `do` | | [Permission.get](/business/nouns/permission/get) | Returns one Permission by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Permission.list](/business/nouns/permission/list) | Returns Permissions, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Permission.update](/business/nouns/permission/update) | Changes the given properties of a Permission. Inherited from [Noun](/business/nouns/noun). | None. | `Permission.updated` | Two-way: `try`, `send`, `do` | | [Permission.delete](/business/nouns/permission/delete) | Deletes a Permission; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Permission.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Permission.create` | Yes | Yes | No | No | | `Permission.get` | Yes | Yes | Yes | Yes | | `Permission.list` | Yes | Yes | Yes | Yes | | `Permission.update` | Yes | Yes | No | No | | `Permission.delete` | Yes | Yes | No | No | ## Call it **Ask** ```text Add a permission to PatentPad. ``` **API** ```bash curl -X POST https://api.sb/patentpad.com/permissions \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"scope":"Example scope"}' ``` ```json { "api": "https://api.sb/patentpad.com", "permission": { "$id": "https://api.sb/patentpad.com/permissions/permission_1", "$type": "Permission", "scope": "Example scope" }, "action": { "$id": "https://api.sb/patentpad.com/actions/action_1", "operation": "Permission.create", "status": "done" }, "links": { "self": "https://api.sb/patentpad.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const permission = await $.Permission.create({ scope: 'Example scope' }) ``` **CLI** ```bash npx startup-builder do Permission.create --json '{"scope":"Example scope"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Permission.create({ scope: 'Example scope' })" } } ``` ## Example The [Billing Specialist](/agents/finance/billing-specialist) Role holds a Permission to `refund` on [Order](/business/nouns/order), within a $100 Limit. # Person URL: /business/nouns/person · Id: `noun:person` > A Person is a human with one identity across every Startup; each Startup’s Contact is its own view of that Person. A Person is a human with one identity across every [Startup](/business/nouns/startup); each Startup’s [Contact](/business/nouns/contact) is its own view of that Person. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `verified` | `boolean` | No | True once the identity is verified. |
Inherited from [Party](/business/nouns/party): 1 property | Property | Type | Required | Description | | --- | --- | --- | --- | | `name` | `string` | Yes | The legal or personal name. |
## Object ```json { "$id": "https://api.sb/patentpad.com/people/person_1", "$type": "Person", "name": "PatentPad", "verified": true } ``` ## Relationships - A Person’s **candidacies** are many [Candidates](/business/nouns/candidate): a [Candidate](/business/nouns/candidate) is one Person’s candidacy; the Person’s record crosses [Startups](/business/nouns/startup) only with [Consent](/business/nouns/consent). `candidacies`, inverse [`presents`](/business/nouns/candidate#rel-presents). - A Person **has** many [Contacts](/business/nouns/contact): each [Contact](/business/nouns/contact) is one [Startup](/business/nouns/startup)’s view of a Person shared across every Startup that knows them. `contacts`, inverse [`resolvesTo`](/business/nouns/contact#rel-resolves-to). - A Person **joins** many [Tenants](/business/nouns/tenant): a Person joins a [Customer](/business/nouns/customer)’s [Tenant](/business/nouns/tenant) as a member, and one Person can join many Tenants. `joins`, inverse [`admits`](/business/nouns/tenant#rel-admits). - A Person **has** many [Voices](/business/nouns/voice): a cloned [Voice](/business/nouns/voice) sounds like one real person, and exists only while that person’s [Consent](/business/nouns/consent) holds. `voices`, inverse [`soundsLike`](/business/nouns/voice#rel-sounds-like). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Person.create](/business/nouns/person/create) | Creates a Person. Inherited from [Noun](/business/nouns/noun). | None. | `Person.created` | Two-way: `try`, `send`, `do` | | [Person.get](/business/nouns/person/get) | Returns one Person by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Person.list](/business/nouns/person/list) | Returns People, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Person.update](/business/nouns/person/update) | Changes the given properties of a Person. Inherited from [Noun](/business/nouns/noun). | None. | `Person.updated` | Two-way: `try`, `send`, `do` | | [Person.delete](/business/nouns/person/delete) | Deletes a Person; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Person.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Person.create` | Yes | Yes | Yes | No | | `Person.get` | Yes | Yes | Yes | Yes | | `Person.list` | Yes | Yes | Yes | Yes | | `Person.update` | Yes | Yes | Yes | No | | `Person.delete` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Add a person to ShiftNote. ``` **API** ```bash curl -X POST https://api.sb/shiftnote.app/people \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"name":"ShiftNote"}' ``` ```json { "api": "https://api.sb/shiftnote.app", "person": { "$id": "https://api.sb/shiftnote.app/people/person_1", "$type": "Person", "name": "Daniel Okafor" }, "action": { "$id": "https://api.sb/shiftnote.app/actions/action_1", "operation": "Person.create", "status": "done" }, "links": { "self": "https://api.sb/shiftnote.app/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const person = await $.Person.create({ name: 'ShiftNote' }) ``` **CLI** ```bash npx startup-builder do Person.create --json '{"name":"ShiftNote"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Person.create({ name: 'ShiftNote' })" } } ``` ## Example A wedding photographer is one Person. To a client-gallery [App](/business/nouns/app) she is a [Customer](/business/nouns/customer)'s Contact, and to a sibling that sells contract templates she is a [Lead](/business/nouns/lead). # Persona URL: /business/nouns/persona · Id: `noun:persona` > A Persona is a named type of person with a job to do, such as a buyer, a seller, or an admin of an App. A Persona is a named type of person with a job to do, such as a buyer, a seller, or an admin of an [App](/business/nouns/app). ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `job` | `text` | Yes | What they come to get done. | | `from` | `string` | No | Lineage: the slot it compiles from, as `Hypothesis#@v`. | ## Object ```json { "$id": "https://api.sb/tutorloop.com/personas/persona_1", "$type": "Persona", "job": "Example job", "from": "Hypothesis#approach@v1" } ``` ## Relationships - A Persona **belongs to** one [ICP](/business/nouns/icp): a Persona is one named role inside an [ICP](/business/nouns/icp), such as its buyer or its admin. `belongsTo`, inverse [`personas`](/business/nouns/icp#rel-personas). - A Persona **holds** one [Role](/business/nouns/role): the [Role](/business/nouns/role) whose [Permissions](/business/nouns/permission) a Persona signs in with, so an [App](/business/nouns/app) compiles its [Dashboards](/business/nouns/dashboard) and [Verbs](/business/nouns/verb) from one record. `holds`, inverse [`personas`](/business/nouns/role#rel-personas). - A Persona **is targeted by** many [Offers](/business/nouns/offer): an [Offer](/business/nouns/offer) speaks to and is priced for named Personas. `targetedBy`, inverse [`targets`](/business/nouns/offer#rel-targets). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Persona.create](/business/nouns/persona/create) | Creates a Persona. Inherited from [Noun](/business/nouns/noun). | None. | `Persona.created` | Two-way: `try`, `send`, `do` | | [Persona.get](/business/nouns/persona/get) | Returns one Persona by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Persona.list](/business/nouns/persona/list) | Returns Personas, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Persona.update](/business/nouns/persona/update) | Changes the given properties of a Persona. Inherited from [Noun](/business/nouns/noun). | None. | `Persona.updated` | Two-way: `try`, `send`, `do` | | [Persona.delete](/business/nouns/persona/delete) | Deletes a Persona; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Persona.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Persona.create` | Yes | Yes | Yes | No | | `Persona.get` | Yes | Yes | Yes | Yes | | `Persona.list` | Yes | Yes | Yes | Yes | | `Persona.update` | Yes | Yes | Yes | No | | `Persona.delete` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Add a persona to QuietCopy. ``` **API** ```bash curl -X POST https://api.sb/quietcopy.com/personas \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"job":"Example job"}' ``` ```json { "api": "https://api.sb/quietcopy.com", "persona": { "$id": "https://api.sb/quietcopy.com/personas/persona_1", "$type": "Persona", "job": "Example job" }, "action": { "$id": "https://api.sb/quietcopy.com/actions/action_1", "operation": "Persona.create", "status": "done" }, "links": { "self": "https://api.sb/quietcopy.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const persona = await $.Persona.create({ job: 'Example job' }) ``` **CLI** ```bash npx startup-builder do Persona.create --json '{"job":"Example job"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Persona.create({ job: 'Example job' })" } } ``` ## Example The App of a tutoring marketplace serves three Personas: the parent who books sessions, the tutor who sets hours, and the admin who settles disputes. # compile URL: /business/nouns/play-mix/compile · Id: `verb:PlayMix.compile` · Call: `await $.PlayMix.compile({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Compile builds the next Play Mix from the Demand Budget, each Play’s ledger and last week’s Acquisitions, and records the diff. Compile builds the next [Play Mix](/business/nouns/play-mix) from the [Demand Budget](/business/nouns/demand-budget), each [Play](/business/nouns/play)’s ledger and last week’s [Acquisitions](/business/nouns/acquisition), and records the diff. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `startup` | [Startup](/business/nouns/startup) | Yes | The Startup whose Play Mix is compiled. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `playMix` | [Play Mix](/business/nouns/play-mix) | Yes | The new version, or the current one when nothing moved. | ## Effects - Emits [`PlayMix.compiled`](/business/events/PlayMix.compiled). - Performed by the [Marketing Lead](/agents/marketing/marketing-lead). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Runs weekly with no caller, before the week’s Decisions are read. - Moves a running Play only when its loop window closes with its sample met, or when a guardrail stops it. - Changes at most two Play states a week. - Funds a paid Play at or above its minimum budget, or not at all. - Logs the propensity of each allocation it randomizes. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [PlayMix.compile](/business/nouns/play-mix/compile) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Compile the latest play mix with a startup. ``` **API** ```bash curl -X POST https://api.sb/routewise.dev/play-mixes/compile \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"startup":"startup_1"}' ``` ```json { "api": "https://api.sb/routewise.dev", "playMix": { "$id": "https://api.sb/routewise.dev/play-mixes/play_mix_1", "$type": "PlayMix", "version": 1, "plays": {}, "compiledAt": "2026-10-22T12:00:00Z" }, "action": { "$id": "https://api.sb/routewise.dev/actions/action_1", "operation": "PlayMix.compile", "status": "done" }, "links": { "self": "https://api.sb/routewise.dev/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const playMix = await $.PlayMix.compile({ startup: 'startup_1' }) ``` **CLI** ```bash npx startup-builder do PlayMix.compile --json '{"startup":"startup_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.PlayMix.compile({ startup: 'startup_1' })" } } ``` # Play Mix URL: /business/nouns/play-mix · Id: `noun:play-mix` > A Play Mix is the set of Plays a Startup runs this week, each with its state, budget and stop rule, compiled weekly and versioned. A Play Mix is the set of [Plays](/business/nouns/play) a [Startup](/business/nouns/startup) runs this week, each with its state, budget and stop rule, compiled weekly and versioned. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `version` | `integer` | Yes | The version number; each weekly compile that changes a Play’s state or budget adds one. | | `plays` | `json` | Yes | Each Play with its state (`gated`, `running` or `paused`), its monthly budget, its stop rule and its payback last week. | | `gates` | `json` | No | Each gate: the Metric and threshold that opens it, and the Plays it opens. | | `crossover` | `string` | No | The reading that ends seed mode, such as compounding share at 50 percent for 4 weeks. | | `diff` | `text` | No | What changed from the previous version, one line per Play, with the reading that moved it. | | `from` | `string` | No | Lineage: the slot it compiles from, as `Hypothesis#@v`. | | `compiledAt` | `datetime` | Yes | When the compile ran. | ## Object ```json { "$id": "https://api.sb/routewise.dev/play-mixes/play_mix_1", "$type": "PlayMix", "version": 1, "plays": {}, "gates": {}, "crossover": "Example crossover", "diff": "Example diff", "from": "Hypothesis#approach@v1", "compiledAt": "2026-10-22T12:00:00Z" } ``` ## Relationships - A Play Mix **allocates** one [Demand Budget](/business/nouns/demand-budget): each Play Mix version splits one [Demand Budget](/business/nouns/demand-budget) across its paid [Plays](/business/nouns/play). `allocates`, inverse [`allocatedBy`](/business/nouns/demand-budget#rel-allocated-by). - A Play Mix **runs** many [Plays](/business/nouns/play): a Play Mix names each [Play](/business/nouns/play) the [Startup](/business/nouns/startup) runs this week, with its state, budget and stop rule. `runs`, inverse [`includedIn`](/business/nouns/play#rel-included-in). - A Play Mix **has** one [Startup](/business/nouns/startup): a [Startup](/business/nouns/startup) compiles one Play Mix version a week and keeps every earlier version for the diff. `startup`, inverse [`compiles`](/business/nouns/startup#rel-compiles). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [PlayMix.compile](/business/nouns/play-mix/compile) | Compile builds the next Play Mix from the Demand Budget, each Play’s ledger and last week’s Acquisitions, and records the diff. | [Marketing Lead](/agents/marketing/marketing-lead) | [`PlayMix.compiled`](/business/events/PlayMix.compiled) | Two-way: `try`, `send`, `do` | | [PlayMix.get](/business/nouns/play-mix/get) | Returns one Play Mix by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [PlayMix.list](/business/nouns/play-mix/list) | Returns Play Mixes, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | A Play Mix is kept forever and never edited: it has no `update` or `delete`. ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `PlayMix.get` | Yes | Yes | Yes | Yes | | `PlayMix.list` | Yes | Yes | Yes | Yes | | `PlayMix.compile` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Compile the latest play mix with a startup. ``` **API** ```bash curl -X POST https://api.sb/routewise.dev/play-mixes/compile \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"startup":"startup_1"}' ``` ```json { "api": "https://api.sb/routewise.dev", "playMix": { "$id": "https://api.sb/routewise.dev/play-mixes/play_mix_1", "$type": "PlayMix", "version": 1, "plays": {}, "compiledAt": "2026-10-22T12:00:00Z" }, "action": { "$id": "https://api.sb/routewise.dev/actions/action_1", "operation": "PlayMix.compile", "status": "done" }, "links": { "self": "https://api.sb/routewise.dev/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const playMix = await $.PlayMix.compile({ startup: 'startup_1' }) ``` **CLI** ```bash npx startup-builder do PlayMix.compile --json '{"startup":"startup_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.PlayMix.compile({ startup: 'startup_1' })" } } ``` ## Example In week six, a bookkeeping-agent Startup compiles Play Mix version 7 against a $1,000 [Demand Budget](/business/nouns/demand-budget). The diff pauses cold email at 0.6 percent positive replies and raises paid search from $850 to $1,000 at a 31-day payback. Answer engine pages and directory listings keep running at $0. # apply URL: /business/nouns/play/apply · Id: `verb:Play.apply` · Call: `await $.Play.apply({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Apply runs a Play across a Portfolio cohort, one wave at a time, measured as an Experiment. Apply runs a [Play](/business/nouns/play) across a [Portfolio](/business/nouns/portfolio) cohort, one wave at a time, measured as an [Experiment](/business/nouns/experiment). ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `play` | [Play](/business/nouns/play) | Yes | The Play to run. | | `cohort` | `string` | Yes | The Portfolio query that selects the Startups. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `experiment` | [Experiment](/business/nouns/experiment) | Yes | The Experiment that measures the rollout. | | `play` | [Play](/business/nouns/play) | Yes | The Play applied. | ## Effects - Emits [`Play.applied`](/business/events/Play.applied). - Performed by the [Marketing Lead](/agents/marketing/marketing-lead). - Tags every write with the Play, so one `revert` undoes the rollout. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The input does not match the schema of the operation. | [`invalid-input`](/code/api/errors/invalid-input) | Read the schema of the operation, then send every required field with the right type. | [Play.apply](/business/nouns/play/apply) | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Play.apply](/business/nouns/play/apply) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Apply the latest play. ``` **API** ```bash curl -X POST https://api.sb/kilnbakery.com/plays/play_1/apply \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"cohort":"Example cohort"}' ``` ```json { "api": "https://api.sb/kilnbakery.com", "experiment": { "$id": "https://api.sb/kilnbakery.com/experiments/experiment_1", "$type": "Experiment", "variants": {} }, "play": { "$id": "https://api.sb/kilnbakery.com/plays/play_1", "$type": "Play", "family": "demand" }, "action": { "$id": "https://api.sb/kilnbakery.com/actions/action_1", "operation": "Play.apply", "status": "done" }, "links": { "self": "https://api.sb/kilnbakery.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { experiment, play } = await $.Play.apply({ play: 'play_1', cohort: 'Example cohort' }) ``` **CLI** ```bash npx startup-builder do Play.apply --json '{"play":"play_1","cohort":"Example cohort"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Play.apply({ play: 'play_1', cohort: 'Example cohort' })" } } ``` # Play URL: /business/nouns/play · Id: `noun:play` > A Play is a named, repeatable strategy with the Metric it moves and its cost, run by a Startup as a Process. A Play is a named, repeatable strategy with the [Metric](/business/nouns/metric) it moves and its cost, run by a [Startup](/business/nouns/startup) as a [Process](/business/nouns/process). A seed Play finds the first [Customers](/business/nouns/customer); a compound Play builds an engine that keeps growing. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `family` | `string` | Yes | The job it does, such as `demand`, `retention`, or `pricing`. | | `cost` | `money` | No | What one run costs. | | `cohort` | `json` | No | The Portfolio query a Studio rolls it out to. | | `from` | `string` | No | Lineage: the slot it compiles from, as `Hypothesis#@v`. | | `spend` | `money` | No | Media, data and creative spend posted against the Play. | | `workerCost` | `money` | No | What the Workers running it cost: model tokens, compute, upstream calls and human minutes. | | `customersAcquired` | `integer` | No | Outside Customers whose Acquisition names the Play. | | `outsideRevenue` | `money` | No | Revenue collected from those Customers, net of refunds. | | `margin` | `money` | No | Outside revenue less spend, Worker cost and the cost to serve those Customers. | | `paybackDays` | `integer` | No | Days from the first spend until margin covers spend and Worker cost; empty until it does. | ## Object ```json { "$id": "https://api.sb/tutorloop.com/plays/play_1", "$type": "Play", "family": "demand", "cost": { "amount": 60, "currency": "USD" }, "cohort": {}, "from": "Hypothesis#approach@v1", "spend": { "amount": 60, "currency": "USD" }, "workerCost": { "amount": 60, "currency": "USD" }, "customersAcquired": 1, "outsideRevenue": { "amount": 60, "currency": "USD" }, "margin": { "amount": 60, "currency": "USD" }, "paybackDays": 1 } ``` ## Relationships - A Play **is carried out by** many [Processes](/business/nouns/process): a [Process](/business/nouns/process) runs the steps of a Play each time the [Startup](/business/nouns/startup) runs it. `carriedOutBy`, inverse [`carriesOut`](/business/nouns/process#rel-carries-out). - A Play **is included in** many [Play Mixes](/business/nouns/play-mix): a [Play Mix](/business/nouns/play-mix) names each Play the [Startup](/business/nouns/startup) runs this week, with its state, budget and stop rule. `includedIn`, inverse [`runs`](/business/nouns/play-mix#rel-runs). - A Play **moves** many [Metrics](/business/nouns/metric): a Play exists to move named [Metrics](/business/nouns/metric), read before and after every run. `moves`, inverse [`movedBy`](/business/nouns/metric#rel-moved-by). - A Play **is paid by** many [Demand Budgets](/business/nouns/demand-budget): a [Demand Budget](/business/nouns/demand-budget)’s spend buys demand Plays. `paidBy`, inverse [`pays`](/business/nouns/demand-budget#rel-pays). - A Play **targets** many [Portfolios](/business/nouns/portfolio): a [Studio](/business/nouns/studio) rolls a Play out across a [Portfolio](/business/nouns/portfolio) one cohort wave at a time, measured as an [Experiment](/business/nouns/experiment). `targets`, inverse [`plays`](/business/nouns/portfolio#rel-plays). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Play.apply](/business/nouns/play/apply) | Apply runs a Play across a Portfolio cohort, one wave at a time, measured as an Experiment. | [Marketing Lead](/agents/marketing/marketing-lead) | [`Play.applied`](/business/events/Play.applied) | None. | | [Play.create](/business/nouns/play/create) | Creates a Play. Inherited from [Noun](/business/nouns/noun). | None. | `Play.created` | Two-way: `try`, `send`, `do` | | [Play.get](/business/nouns/play/get) | Returns one Play by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Play.list](/business/nouns/play/list) | Returns Plays, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Play.update](/business/nouns/play/update) | Changes the given properties of a Play. Inherited from [Noun](/business/nouns/noun). | None. | `Play.updated` | Two-way: `try`, `send`, `do` | | [Play.delete](/business/nouns/play/delete) | Deletes a Play; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Play.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Play.create` | Yes | Yes | Yes | No | | `Play.get` | Yes | Yes | Yes | Yes | | `Play.list` | Yes | Yes | Yes | Yes | | `Play.update` | Yes | Yes | Yes | No | | `Play.delete` | Yes | Yes | Yes | No | | `Play.apply` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Apply the latest play. ``` **API** ```bash curl -X POST https://api.sb/kilnbakery.com/plays/play_1/apply \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"cohort":"Example cohort"}' ``` ```json { "api": "https://api.sb/kilnbakery.com", "experiment": { "$id": "https://api.sb/kilnbakery.com/experiments/experiment_1", "$type": "Experiment", "variants": {} }, "play": { "$id": "https://api.sb/kilnbakery.com/plays/play_1", "$type": "Play", "family": "demand" }, "action": { "$id": "https://api.sb/kilnbakery.com/actions/action_1", "operation": "Play.apply", "status": "done" }, "links": { "self": "https://api.sb/kilnbakery.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { experiment, play } = await $.Play.apply({ play: 'play_1', cohort: 'Example cohort' }) ``` **CLI** ```bash npx startup-builder do Play.apply --json '{"play":"play_1","cohort":"Example cohort"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Play.apply({ play: 'play_1', cohort: 'Example cohort' })" } } ``` ## Example A creator-partnership Play gives a cooking creator 15% of the revenue her followers bring to a meal-planning [App](/business/nouns/app). It moves paid signups, costs nothing until a sale, and runs as a seed Play. After 60 days its ledger shows 23 Customers acquired, $1,840 in `outsideRevenue` and a `paybackDays` of 9. # Policy URL: /business/nouns/policy · Id: `noun:policy` > A Policy is a ruling a Startup declares on how its numbers are computed or its choices made, such as revenue recognition. A Policy is a ruling a [Startup](/business/nouns/startup) declares on how its numbers are computed or its choices made, such as revenue recognition. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `rule` | `text` | Yes | The ruling, stated so code can apply it. | ## Object ```json { "$id": "https://api.sb/quietcopy.com/policies/policy_1", "$type": "Policy", "rule": "Example rule" } ``` ## Relationships - A Policy **computes** many [Metrics](/business/nouns/metric): a Policy rules how [Metrics](/business/nouns/metric) are computed, such as revenue under revenue recognition. `computes`, inverse [`computedUnder`](/business/nouns/metric#rel-computed-under). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Policy.create](/business/nouns/policy/create) | Creates a Policy. Inherited from [Noun](/business/nouns/noun). | None. | `Policy.created` | Two-way: `try`, `send`, `do` | | [Policy.get](/business/nouns/policy/get) | Returns one Policy by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Policy.list](/business/nouns/policy/list) | Returns Policies, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Policy.update](/business/nouns/policy/update) | Changes the given properties of a Policy. Inherited from [Noun](/business/nouns/noun). | None. | `Policy.updated` | Two-way: `try`, `send`, `do` | | [Policy.delete](/business/nouns/policy/delete) | Deletes a Policy; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Policy.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Policy.create` | Yes | Yes | No | No | | `Policy.get` | Yes | Yes | Yes | Yes | | `Policy.list` | Yes | Yes | Yes | Yes | | `Policy.update` | Yes | Yes | No | No | | `Policy.delete` | Yes | Yes | No | No | ## Call it **Ask** ```text Add a policy to TutorLoop. ``` **API** ```bash curl -X POST https://api.sb/tutorloop.com/policies \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"rule":"Example rule"}' ``` ```json { "api": "https://api.sb/tutorloop.com", "policy": { "$id": "https://api.sb/tutorloop.com/policies/policy_1", "$type": "Policy", "rule": "Example rule" }, "action": { "$id": "https://api.sb/tutorloop.com/actions/action_1", "operation": "Policy.create", "status": "done" }, "links": { "self": "https://api.sb/tutorloop.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const policy = await $.Policy.create({ rule: 'Example rule' }) ``` **CLI** ```bash npx startup-builder do Policy.create --json '{"rule":"Example rule"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Policy.create({ rule: 'Example rule' })" } } ``` ## Example The revenue recognition Policy of a bookkeeping service recognizes each $2,400 catch-up engagement month by month as the books are delivered, not at payment. # Portal URL: /business/nouns/portal · Id: `noun:portal` > A Portal is the signed-in part of a Site where each Customer orders, tracks delivery, accepts work, and pays, seeing only their own records. A Portal is the signed-in part of a [Site](/business/nouns/site) where each [Customer](/business/nouns/customer) orders, tracks delivery, accepts work, and pays, seeing only their own records. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `path` | `string` | Yes | Where it is mounted on the Site, `/portal` by default. | | `tools` | `string[]` | No | Developer tools a keyed Offer adds: `keys`, `usage`, `requests`, `watches`, `version` and `testMode`. | ## Object ```json { "$id": "https://api.sb/tutorloop.com/portals/portal_1", "$type": "Portal", "path": "/", "tools": [ "keys" ] } ``` ## Relationships - A Portal **is included in** one [Site](/business/nouns/site): a [Site](/business/nouns/site) includes one Portal, the signed-in part where each [Customer](/business/nouns/customer) sees only their own records. `includedIn`, inverse [`includes`](/business/nouns/site#rel-includes). - A Portal **serves** many [Customers](/business/nouns/customer): [Customers](/business/nouns/customer) sign in to a Portal to order, track delivery, accept work, and pay. `serves`, inverse [`signsInto`](/business/nouns/customer#rel-signs-into). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Portal.create](/business/nouns/portal/create) | Creates a Portal. Inherited from [Noun](/business/nouns/noun). | None. | `Portal.created` | Two-way: `try`, `send`, `do` | | [Portal.get](/business/nouns/portal/get) | Returns one Portal by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Portal.list](/business/nouns/portal/list) | Returns Portals, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Portal.update](/business/nouns/portal/update) | Changes the given properties of a Portal. Inherited from [Noun](/business/nouns/noun). | None. | `Portal.updated` | Two-way: `try`, `send`, `do` | | [Portal.delete](/business/nouns/portal/delete) | Deletes a Portal; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Portal.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Portal.create` | Yes | Yes | Yes | No | | `Portal.get` | Yes | Yes | Yes | Yes | | `Portal.list` | Yes | Yes | Yes | Yes | | `Portal.update` | Yes | Yes | Yes | No | | `Portal.delete` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Add a portal to QuietCopy. ``` **API** ```bash curl -X POST https://api.sb/quietcopy.com/portals \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"path":"/"}' ``` ```json { "api": "https://api.sb/quietcopy.com", "portal": { "$id": "https://api.sb/quietcopy.com/portals/portal_1", "$type": "Portal", "path": "/" }, "action": { "$id": "https://api.sb/quietcopy.com/actions/action_1", "operation": "Portal.create", "status": "done" }, "links": { "self": "https://api.sb/quietcopy.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const portal = await $.Portal.create({ path: '/' }) ``` **CLI** ```bash npx startup-builder do Portal.create --json '{"path":"/"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Portal.create({ path: '/' })" } } ``` ## Example A client of a bookkeeping service signs in at `/portal`, accepts last month's close, uploads two receipts, and pays the [Invoice](/business/nouns/invoice). She sees only her own records. # brake URL: /business/nouns/portfolio/brake · Id: `verb:Portfolio.brake` · Call: `await $.Portfolio.brake({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Brake stops one class of effects, such as sends, spend, publishes, or price changes, across a Portfolio query until it expires or is lifted. Brake stops one class of effects, such as sends, spend, publishes, or price changes, across a [Portfolio](/business/nouns/portfolio) query until it expires or is lifted. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `portfolio` | [Portfolio](/business/nouns/portfolio) | Yes | The Portfolio whose Startups the brake covers. | | `effects` | `string[]` | Yes | Any of `send`, `spend`, `publish`, and `price`. | | `reason` | `text` | Yes | Why the effects stop. | | `until` | `datetime` | Yes | When the brake expires. | | `query` | `string` | No | Narrows the brake to the Startups that match, such as one Startup Template Version or one Cohort. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `brake` | [Setting](/business/nouns/setting) | Yes | The brake, held as a Setting that every matching Startup inherits. | | `portfolio` | [Portfolio](/business/nouns/portfolio) | Yes | The Portfolio under the brake. | ## Effects - Emits [`Portfolio.braked`](/business/events/Portfolio.braked). - Holds every new Action of a braked effect as `pending` until the brake ends; nothing already `done` is undone. - Records a Decision with the reason. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Portfolio.brake](/business/nouns/portfolio/brake) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Brake the latest portfolio. ``` **API** ```bash curl -X POST https://api.sb/ledgerlark.com/portfolios/portfolio_1/brake \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"effects":["send"],"reason":"Example reason","until":"2026-10-22T12:00:00Z"}' ``` ```json { "api": "https://api.sb/ledgerlark.com", "brake": { "$id": "https://api.sb/ledgerlark.com/settings/setting_1", "$type": "Setting", "key": "Example key", "value": {} }, "portfolio": { "$id": "https://api.sb/ledgerlark.com/portfolios/portfolio_1", "$type": "Portfolio", "id": "Example id", "type": [ "noun_1" ] }, "action": { "$id": "https://api.sb/ledgerlark.com/actions/action_1", "operation": "Portfolio.brake", "status": "done" }, "links": { "self": "https://api.sb/ledgerlark.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { brake, portfolio } = await $.Portfolio.brake({ portfolio: 'portfolio_1', effects: ['send'], reason: 'Example reason', until: '2026-10-22T12:00:00Z' }) ``` **CLI** ```bash npx startup-builder do Portfolio.brake --json '{"portfolio":"portfolio_1","effects":["send"],"reason":"Example reason","until":"2026-10-22T12:00:00Z"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Portfolio.brake({ portfolio: 'portfolio_1', effects: ['send'], reason: 'Example reason', until: '2026-10-22T12:00:00Z' })" } } ``` # Portfolio URL: /business/nouns/portfolio · Id: `noun:portfolio` > A Portfolio is a managed set a Thing allocates attention and money across, by membership: a Studio’s Startups, a Startup’s child Startups, or its Products. A Portfolio is a managed set of [Startups](/business/nouns/startup) or [Products](/business/nouns/product) that a [Studio](/business/nouns/studio), [Company](/business/nouns/company), or Startup allocates attention and money across. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `membership` | `string` | No | How each member belongs: `held`, `owned`, `contracted`, or `made`. |
Inherited from [Collection](/business/nouns/collection): 1 property | Property | Type | Required | Description | | --- | --- | --- | --- | | `query` | `json` | No | The saved query that defines a dynamic Collection. |
Inherited from [Thing](/business/nouns/thing): 4 properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `id` | `string` | Yes | The stable identifier, which never changes. | | `type` | list of [Noun](/business/nouns/noun) | Yes | The Nouns this Thing is an instance of. | | `state` | `string` | No | The current state in its lifecycle. | | `outside` | `json` | No | The ids this Thing has in outside tools, one per Integration, so a re-run matches instead of duplicating. |
## Object ```json { "$id": "https://api.sb/tutorloop.com/portfolios/portfolio_1", "$type": "Portfolio", "id": "Example id", "type": [ "noun_1" ], "state": "Example state", "outside": {}, "query": {}, "membership": "held" } ``` ## Relationships - A Portfolio **has** many [Cohorts](/business/nouns/cohort): a [Cohort](/business/nouns/cohort) selects its [Startups](/business/nouns/startup) from one Portfolio by a saved query. `cohorts`, inverse [`drawnFrom`](/business/nouns/cohort#rel-drawn-from). - A Portfolio **includes startup** many [Startups](/business/nouns/startup): a [Startup](/business/nouns/startup) can sit in many Portfolios, each with its own membership: held, owned, contracted or made. `includesStartup`, inverse [`portfolios`](/business/nouns/startup#rel-portfolios). - A Portfolio **is managed by** one [Studio](/business/nouns/studio): a [Studio](/business/nouns/studio) allocates attention and money across the members of each Portfolio it manages. `managedBy`, inverse [`manages`](/business/nouns/studio#rel-manages). - A Portfolio **has** many [Plays](/business/nouns/play): a [Studio](/business/nouns/studio) rolls a [Play](/business/nouns/play) out across a Portfolio one cohort wave at a time, measured as an [Experiment](/business/nouns/experiment). `plays`, inverse [`targets`](/business/nouns/play#rel-targets). - A Portfolio **has** many [Risks](/business/nouns/risk): [Exposure](/business/nouns/exposure) shared across sibling [Startups](/business/nouns/startup), such as one upstream every sibling relies on. `risks`, inverse [`portfolio`](/business/nouns/risk#rel-portfolio). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Portfolio.brake](/business/nouns/portfolio/brake) | Brake stops one class of effects, such as sends, spend, publishes, or price changes, across a Portfolio query until it expires or is lifted. | [Worker](/business/nouns/worker) | [`Portfolio.braked`](/business/events/Portfolio.braked) | None. | | [Portfolio.lift](/business/nouns/portfolio/lift) | Lift ends a brake before it expires, and the Actions it held resume their review and delay windows. | [Worker](/business/nouns/worker) | [`Portfolio.lifted`](/business/events/Portfolio.lifted) | None. | | [Portfolio.create](/business/nouns/portfolio/create) | Creates a Portfolio. Inherited from [Noun](/business/nouns/noun). | None. | `Portfolio.created` | Two-way: `try`, `send`, `do` | | [Portfolio.get](/business/nouns/portfolio/get) | Returns one Portfolio by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Portfolio.list](/business/nouns/portfolio/list) | Returns Portfolios, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Portfolio.update](/business/nouns/portfolio/update) | Changes the given properties of a Portfolio. Inherited from [Noun](/business/nouns/noun). | None. | `Portfolio.updated` | Two-way: `try`, `send`, `do` | | [Portfolio.delete](/business/nouns/portfolio/delete) | Deletes a Portfolio; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Portfolio.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Portfolio.create` | Yes | Yes | Yes | No | | `Portfolio.get` | Yes | Yes | Yes | Yes | | `Portfolio.list` | Yes | Yes | Yes | Yes | | `Portfolio.update` | Yes | Yes | Yes | No | | `Portfolio.delete` | Yes | Yes | Yes | No | | `Portfolio.brake` | Yes | Yes | Yes | No | | `Portfolio.lift` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Brake the latest portfolio. ``` **API** ```bash curl -X POST https://api.sb/ledgerlark.com/portfolios/portfolio_1/brake \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"effects":["send"],"reason":"Example reason","until":"2026-10-22T12:00:00Z"}' ``` ```json { "api": "https://api.sb/ledgerlark.com", "brake": { "$id": "https://api.sb/ledgerlark.com/settings/setting_1", "$type": "Setting", "key": "Example key", "value": {} }, "portfolio": { "$id": "https://api.sb/ledgerlark.com/portfolios/portfolio_1", "$type": "Portfolio", "id": "Example id", "type": [ "noun_1" ] }, "action": { "$id": "https://api.sb/ledgerlark.com/actions/action_1", "operation": "Portfolio.brake", "status": "done" }, "links": { "self": "https://api.sb/ledgerlark.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { brake, portfolio } = await $.Portfolio.brake({ portfolio: 'portfolio_1', effects: ['send'], reason: 'Example reason', until: '2026-10-22T12:00:00Z' }) ``` **CLI** ```bash npx startup-builder do Portfolio.brake --json '{"portfolio":"portfolio_1","effects":["send"],"reason":"Example reason","until":"2026-10-22T12:00:00Z"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Portfolio.brake({ portfolio: 'portfolio_1', effects: ['send'], reason: 'Example reason', until: '2026-10-22T12:00:00Z' })" } } ``` ## Example A Studio's Portfolio holds 40 Startups. It moves its weekly budget toward the 6 that are default alive and growing. # lift URL: /business/nouns/portfolio/lift · Id: `verb:Portfolio.lift` · Call: `await $.Portfolio.lift({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Lift ends a brake before it expires, and the Actions it held resume their review and delay windows. Lift ends a brake before it expires, and the [Actions](/business/nouns/action) it held resume their review and delay windows. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `portfolio` | [Portfolio](/business/nouns/portfolio) | Yes | The braked Portfolio. | | `brake` | [Setting](/business/nouns/setting) | Yes | The brake to lift. | | `reason` | `text` | Yes | Why the effects may resume. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `brake` | [Setting](/business/nouns/setting) | Yes | The lifted brake, kept on record. | | `portfolio` | [Portfolio](/business/nouns/portfolio) | Yes | The Portfolio, its brake lifted. | ## Effects - Emits [`Portfolio.lifted`](/business/events/Portfolio.lifted). - Records a Decision with the reason. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Portfolio.lift](/business/nouns/portfolio/lift) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Lift the latest portfolio with a setting. ``` **API** ```bash curl -X POST https://api.sb/ledgerlark.com/portfolios/portfolio_1/lift \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"brake":"setting_1","reason":"Example reason"}' ``` ```json { "api": "https://api.sb/ledgerlark.com", "brake": { "$id": "https://api.sb/ledgerlark.com/settings/setting_1", "$type": "Setting", "key": "Example key", "value": {} }, "portfolio": { "$id": "https://api.sb/ledgerlark.com/portfolios/portfolio_1", "$type": "Portfolio", "id": "Example id", "type": [ "noun_1" ] }, "action": { "$id": "https://api.sb/ledgerlark.com/actions/action_1", "operation": "Portfolio.lift", "status": "done" }, "links": { "self": "https://api.sb/ledgerlark.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { brake, portfolio } = await $.Portfolio.lift({ portfolio: 'portfolio_1', brake: 'setting_1', reason: 'Example reason' }) ``` **CLI** ```bash npx startup-builder do Portfolio.lift --json '{"portfolio":"portfolio_1","brake":"setting_1","reason":"Example reason"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Portfolio.lift({ portfolio: 'portfolio_1', brake: 'setting_1', reason: 'Example reason' })" } } ``` # Post URL: /business/nouns/post · Id: `noun:post` > A Post is something a Handle publishes, such as a thread or a short video, with the reach and replies it earns. A Post is something a [Handle](/business/nouns/handle) publishes, such as a thread or a short video, with the reach and replies it earns. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `format` | `string` | Yes | The venue’s format, such as `shortVideo` or `thread`. | | `publishAt` | `datetime` | No | When it goes out. | | `status` | `string` | Yes | Where it stands; a withdrawn Post is kept with its reach and replies. | | `claims` | `json` | No | The facts it states, each resolving to a record. | | `reach` | `integer` | No | How many people saw it, as the venue reports. | ## Object ```json { "$id": "https://api.sb/quietcopy.com/posts/post_1", "$type": "Post", "format": "Example format", "publishAt": "2026-10-22T12:00:00Z", "status": "draft", "claims": {}, "reach": 1 } ``` ## Relationships - A Post **has** one [Handle](/business/nouns/handle): every Post goes out from one [Handle](/business/nouns/handle), so its reach and replies count toward that Handle. `handle`, inverse [`publishes`](/business/nouns/handle#rel-publishes). ## Lifecycle | State | Meaning | Moves to | | --- | --- | --- | | `draft` (first) | Written and not on its Handle’s calendar. | `scheduled` by [Post.schedule](/business/nouns/post/schedule); `published` by [Post.publish](/business/nouns/post/publish) | | `scheduled` | On its Handle’s calendar for `publishAt`. | `published` by [Post.publish](/business/nouns/post/publish) | | `published` | Live on its venue, earning reach and replies. | `withdrawn` by [Post.withdraw](/business/nouns/post/withdraw) | | `withdrawn` | Taken down from its venue, with its record, reach and replies kept. | None: it ends here. | ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Post.publish](/business/nouns/post/publish) | Publish sends a Post out through its Handle once every claim it states resolves to a live record. | [Content Lead](/agents/marketing/content-lead) | [`Post.published`](/business/events/Post.published) | One-way (brand): `send`, `do` | | [Post.schedule](/business/nouns/post/schedule) | Schedule puts a drafted Post on its Handle’s calendar for a set time. | [Content Lead](/agents/marketing/content-lead) | [`Post.scheduled`](/business/events/Post.scheduled) | Two-way: `try`, `send`, `do` | | [Post.withdraw](/business/nouns/post/withdraw) | Withdraw takes a published Post down from its venue and keeps the record, its reach and its replies. | [Content Lead](/agents/marketing/content-lead) | [`Post.withdrawn`](/business/events/Post.withdrawn) | One-way: `send`, `do` | | [Post.create](/business/nouns/post/create) | Creates a Post. Inherited from [Noun](/business/nouns/noun). | None. | `Post.created` | Two-way: `try`, `send`, `do` | | [Post.get](/business/nouns/post/get) | Returns one Post by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Post.list](/business/nouns/post/list) | Returns Posts, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Post.update](/business/nouns/post/update) | Changes the given properties of a Post. Inherited from [Noun](/business/nouns/noun). | None. | `Post.updated` | Two-way: `try`, `send`, `do` | A Post is never deleted: it ends by [Post.withdraw](/business/nouns/post/withdraw), and its records stay. ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Post.create` | Yes | Yes | Yes | No | | `Post.get` | Yes | Yes | Yes | Yes | | `Post.list` | Yes | Yes | Yes | Yes | | `Post.update` | Yes | Yes | Yes | No | | `Post.publish` | Yes | No | No | No | | `Post.schedule` | Yes | Yes | Yes | No | | `Post.withdraw` | Yes | No | No | No | ## Call it **Ask** ```text Schedule the latest post. ``` **API** ```bash curl -X POST https://api.sb/ledgerlark.com/posts/post_1/schedule \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"at":"2026-10-22T12:00:00Z"}' ``` ```json { "api": "https://api.sb/ledgerlark.com", "post": { "$id": "https://api.sb/ledgerlark.com/posts/post_1", "$type": "Post", "format": "Example format", "status": "draft" }, "action": { "$id": "https://api.sb/ledgerlark.com/actions/action_1", "operation": "Post.schedule", "status": "done" }, "links": { "self": "https://api.sb/ledgerlark.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const post = await $.Post.schedule({ post: 'post_1', at: '2026-10-22T12:00:00Z' }) ``` **CLI** ```bash npx startup-builder do Post.schedule --json '{"post":"post_1","at":"2026-10-22T12:00:00Z"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Post.schedule({ post: 'post_1', at: '2026-10-22T12:00:00Z' })" } } ``` ## Example A gardening app's [Handle](/business/nouns/handle) publishes a `thread` on frost dates at 7 a.m. Its one claim resolves to a dataset record, and it reaches 12,000 people with 40 replies. # publish URL: /business/nouns/post/publish · Id: `verb:Post.publish` · Call: `await $.Post.publish({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Publish sends a Post out through its Handle once every claim it states resolves to a live record. Publish sends a [Post](/business/nouns/post) out through its [Handle](/business/nouns/handle) once every claim it states resolves to a live record. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `post` | [Post](/business/nouns/post) | Yes | The Post to publish. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `post` | [Post](/business/nouns/post) | Yes | The published Post. | ## Effects - Emits [`Post.published`](/business/events/Post.published). - Performed by the [Content Lead](/agents/marketing/content-lead). - One-way (brand): it waits out its delay window, and runs in the `send` and `do` modes. - A shared Studio Handle names the Startup the Post speaks for. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Post.publish](/business/nouns/post/publish) | ## When it waits | Gate | Default | | --- | --- | | Decision class | High: one-way, broad (brand) | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | 1 business day, in which a watcher can pause, redirect or cancel it; then it runs. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Publish the latest post. ``` **API** ```bash curl -X POST https://api.sb/ledgerlark.com/posts/post_1/publish \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/ledgerlark.com", "post": { "$id": "https://api.sb/ledgerlark.com/posts/post_1", "$type": "Post", "format": "Example format", "status": "draft" }, "action": { "$id": "https://api.sb/ledgerlark.com/actions/action_1", "operation": "Post.publish", "status": "done" }, "links": { "self": "https://api.sb/ledgerlark.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const post = await $.Post.publish({ post: 'post_1' }) ``` **CLI** ```bash npx startup-builder do Post.publish --json '{"post":"post_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Post.publish({ post: 'post_1' })" } } ``` # schedule URL: /business/nouns/post/schedule · Id: `verb:Post.schedule` · Call: `await $.Post.schedule({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Schedule puts a drafted Post on its Handle’s calendar for a set time. Schedule puts a drafted [Post](/business/nouns/post) on its [Handle](/business/nouns/handle)’s calendar for a set time. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `post` | [Post](/business/nouns/post) | Yes | The drafted Post. | | `at` | `datetime` | Yes | When it goes out. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `post` | [Post](/business/nouns/post) | Yes | The scheduled Post. | ## Effects - Emits [`Post.scheduled`](/business/events/Post.scheduled). - Performed by the [Content Lead](/agents/marketing/content-lead). - Two-way: it runs at once, in the `try`, `send` and `do` modes. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Post.schedule](/business/nouns/post/schedule) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Schedule the latest post. ``` **API** ```bash curl -X POST https://api.sb/ledgerlark.com/posts/post_1/schedule \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"at":"2026-10-22T12:00:00Z"}' ``` ```json { "api": "https://api.sb/ledgerlark.com", "post": { "$id": "https://api.sb/ledgerlark.com/posts/post_1", "$type": "Post", "format": "Example format", "status": "draft" }, "action": { "$id": "https://api.sb/ledgerlark.com/actions/action_1", "operation": "Post.schedule", "status": "done" }, "links": { "self": "https://api.sb/ledgerlark.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const post = await $.Post.schedule({ post: 'post_1', at: '2026-10-22T12:00:00Z' }) ``` **CLI** ```bash npx startup-builder do Post.schedule --json '{"post":"post_1","at":"2026-10-22T12:00:00Z"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Post.schedule({ post: 'post_1', at: '2026-10-22T12:00:00Z' })" } } ``` # withdraw URL: /business/nouns/post/withdraw · Id: `verb:Post.withdraw` · Call: `await $.Post.withdraw({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Withdraw takes a published Post down from its venue and keeps the record, its reach and its replies. Withdraw takes a published [Post](/business/nouns/post) down from its venue and keeps the record, its reach and its replies. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `post` | [Post](/business/nouns/post) | Yes | The Post to take down. | | `reason` | `text` | Yes | Why it comes down. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `post` | [Post](/business/nouns/post) | Yes | The withdrawn Post. | ## Effects - Emits [`Post.withdrawn`](/business/events/Post.withdrawn). - Performed by the [Content Lead](/agents/marketing/content-lead). - One-way: it waits out its delay window, and runs in the `send` and `do` modes. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Post.withdraw](/business/nouns/post/withdraw) | ## When it waits | Gate | Default | | --- | --- | | Decision class | High: one-way, broad | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | 1 business day, in which a watcher can pause, redirect or cancel it; then it runs. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Withdraw the latest post. ``` **API** ```bash curl -X POST https://api.sb/kilnbakery.com/posts/post_1/withdraw \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"reason":"Example reason"}' ``` ```json { "api": "https://api.sb/kilnbakery.com", "post": { "$id": "https://api.sb/kilnbakery.com/posts/post_1", "$type": "Post", "format": "Example format", "status": "draft" }, "action": { "$id": "https://api.sb/kilnbakery.com/actions/action_1", "operation": "Post.withdraw", "status": "done" }, "links": { "self": "https://api.sb/kilnbakery.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const post = await $.Post.withdraw({ post: 'post_1', reason: 'Example reason' }) ``` **CLI** ```bash npx startup-builder do Post.withdraw --json '{"post":"post_1","reason":"Example reason"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Post.withdraw({ post: 'post_1', reason: 'Example reason' })" } } ``` # Price URL: /business/nouns/price · Id: `noun:price` > A Price is the amount, currency, unit, and tiers of an Offer, embedded in it; zero is a Price. A Price is the amount, currency, unit, and tiers of an [Offer](/business/nouns/offer), embedded in it; zero is a Price. A new Price is tested on a sibling Offer, never split within one. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `amount` | `money` | Yes | The amount and currency. One Offer has one amount per market: test a sibling Offer instead. Never randomized. | | `unit` | `string` | Yes | What one unit is, such as a seat, a call, or a month. | | `meter` | [Meter](/business/nouns/meter) | No | The Meter that counts usage, for usage pricing. | | `from` | `string` | No | Lineage: the slot it compiles from, as `Hypothesis#@v`. | | `status` | `string` | Yes | One of `draft`, `fixed` or `retired`, set by its Offer. | ## Object ```json { "$id": "https://api.sb/ledgerlark.com/prices/price_1", "$type": "Price", "amount": { "amount": 400, "currency": "USD" }, "unit": "seat", "meter": "meter_1", "from": "Hypothesis#approach@v1", "status": "draft" } ``` ## Relationships - A Price **is a price of** one [Offer](/business/nouns/offer): every [Offer](/business/nouns/offer) embeds one Price: amount, currency, unit and tiers; zero is a Price. `priceOf`, inverse [`pricedAt`](/business/nouns/offer#rel-priced-at). ## Lifecycle | State | Meaning | Moves to | | --- | --- | --- | | `draft` (first) | Its Offer is a draft, so its amount, unit and tiers can still change. | `fixed` on [`Offer.published`](/business/events/Offer.published) when the Offer holds this Price | | `fixed` | Its Offer is published, so it never changes; a new price is a new Offer. | `retired` on [`Offer.withdrawn`](/business/events/Offer.withdrawn) when the Offer holds this Price | | `retired` | Its Offer is withdrawn; every Order and Subscription made at it keeps it. | None: it ends here. | ## Stripe **Price** (`price`). The source of truth is db.sb, and Stripe holds a copy written from it. | Property | Stripe field | Source of truth | | --- | --- | --- | | `amount` | `unit_amount` | db.sb | | `meter` | `recurring.meter` | db.sb | ## Example A currency-conversion API prices each conversion at `amount: 0.001` on the `conversion` [Meter](/business/nouns/meter), with the first 1,000 each month at zero. A sibling Offer tests `amount: 0.0008` in a second [Market](/business/nouns/market). # Problem URL: /business/nouns/problem · Id: `noun:problem` > A Problem is what an ICP struggles with, in their own words: how they solve it today and what it costs them. A Problem is what an [ICP](/business/nouns/icp) struggles with, in their own words: how they solve it today and what it costs them. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `statement` | `text` | Yes | The struggle, in the words of the ICP. | | `costPerPeriod` | `json` | No | What the Problem costs the ICP per period: hours times wage, or the spend on what they hire today. | | `address` | `json` | No | The opportunity map cell it sits on: an occupation, a task it performs, and an industry. | | `moment` | `text` | No | The moment the job starts, with the observable trigger that marks it. | | `progress` | `text` | No | The progress the ICP wants, from the state before to the state after. | | `hiredToday` | `json` | No | What the ICP hires for the job today, by kind and cost: software, a Service, their own hands, or nothing. | ## Object ```json { "$id": "https://api.sb/routewise.dev/problems/problem_1", "$type": "Problem", "statement": "Plans delivery routes for courier fleets through an API.", "costPerPeriod": {}, "address": {}, "moment": "Example moment", "progress": "Example progress", "hiredToday": {} } ``` ## Relationships - A Problem **is addressed by** many [Issues](/business/nouns/issue): an [Issue](/business/nouns/issue) addresses the Problems its [Evidence](/business/nouns/evidence) came from, so the [Customers](/business/nouns/customer) behind that Evidence hear when it ships. `addressedBy`, inverse [`addresses`](/business/nouns/issue#rel-addresses). - A Problem **is documented by** many pieces of [Evidence](/business/nouns/evidence): [Evidence](/business/nouns/evidence) shows a Problem in the words or behavior of the [ICP](/business/nouns/icp). `documentedBy`, inverse [`documents`](/business/nouns/evidence#rel-documents). - A Problem **is faced by** many [ICPs](/business/nouns/icp): an [ICP](/business/nouns/icp) struggles with Problems: how they solve them today and what that costs. `facedBy`, inverse [`faces`](/business/nouns/icp#rel-faces). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Problem.rank](/business/nouns/problem/rank) | Rank orders Problems by revenue at stake, Evidence grade and effort, so the next Project addresses the top one. | [Product Lead](/agents/product/product-lead) | [`Problem.ranked`](/business/events/Problem.ranked) | Two-way: `try`, `send`, `do` | | [Problem.suggest](/business/nouns/problem/suggest) | Suggest records a Customer’s ask for something the Product lacks as Evidence on a Problem, with the asker attached. | [Party](/business/nouns/party) | [`Problem.suggested`](/business/events/Problem.suggested) | Two-way: `try`, `send`, `do` | | [Problem.create](/business/nouns/problem/create) | Creates a Problem. Inherited from [Noun](/business/nouns/noun). | None. | `Problem.created` | Two-way: `try`, `send`, `do` | | [Problem.get](/business/nouns/problem/get) | Returns one Problem by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Problem.list](/business/nouns/problem/list) | Returns Problems, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Problem.update](/business/nouns/problem/update) | Changes the given properties of a Problem. Inherited from [Noun](/business/nouns/noun). | None. | `Problem.updated` | Two-way: `try`, `send`, `do` | | [Problem.delete](/business/nouns/problem/delete) | Deletes a Problem; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Problem.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Problem.create` | Yes | Yes | Yes | No | | `Problem.get` | Yes | Yes | Yes | Yes | | `Problem.list` | Yes | Yes | Yes | Yes | | `Problem.update` | Yes | Yes | Yes | No | | `Problem.delete` | Yes | Yes | Yes | No | | `Problem.rank` | Yes | Yes | Yes | No | | `Problem.suggest` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Suggest the latest problem. ``` **API** ```bash curl -X POST https://api.sb/routewise.dev/problems/suggest \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"text":"Example text"}' ``` ```json { "api": "https://api.sb/routewise.dev", "evidence": { "$id": "https://api.sb/routewise.dev/evidence/evidence_1", "$type": "Evidence", "grade": "Behavior" }, "problem": { "$id": "https://api.sb/routewise.dev/problems/problem_1", "$type": "Problem", "statement": "Plans delivery routes for courier fleets through an API." }, "action": { "$id": "https://api.sb/routewise.dev/actions/action_1", "operation": "Problem.suggest", "status": "done" }, "links": { "self": "https://api.sb/routewise.dev/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { evidence, problem } = await $.Problem.suggest({ text: 'Example text' }) ``` **CLI** ```bash npx startup-builder do Problem.suggest --json '{"text":"Example text"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Problem.suggest({ text: 'Example text' })" } } ``` ## Example A litigation-support firm pulls 300 dockets a week from eight court sites by hand, and it takes two paralegals a full day. That is the Problem, in their words. # rank URL: /business/nouns/problem/rank · Id: `verb:Problem.rank` · Call: `await $.Problem.rank({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Rank orders Problems by revenue at stake, Evidence grade and effort, so the next Project addresses the top one. Rank orders [Problems](/business/nouns/problem) by revenue at stake, [Evidence](/business/nouns/evidence) grade and effort, so the next [Project](/business/nouns/project) addresses the top one. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `icp` | [ICP](/business/nouns/icp) | No | The ICP whose Problems to rank; omitted, every ICP. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `problems` | list of [Problem](/business/nouns/problem) | Yes | Problems, highest first, each with its score. | ## Effects - Emits [`Problem.ranked`](/business/events/Problem.ranked). - Performed by the [Product Lead](/agents/product/product-lead). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Reads the Founding Hypothesis slot each Problem binds to and its weakest Evidence grade. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Problem.rank](/business/nouns/problem/rank) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Rank the latest problem. ``` **API** ```bash curl -X POST https://api.sb/patentpad.com/problems/rank \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"icp":"icp_1"}' ``` ```json { "api": "https://api.sb/patentpad.com", "problems": [ { "$id": "https://api.sb/patentpad.com/problems/problem_1", "$type": "Problem", "statement": "Drafts provisional patents for solo inventors." } ], "action": { "$id": "https://api.sb/patentpad.com/actions/action_1", "operation": "Problem.rank", "status": "done" }, "links": { "self": "https://api.sb/patentpad.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const problems = await $.Problem.rank({ icp: 'icp_1' }) ``` **CLI** ```bash npx startup-builder do Problem.rank --json '{"icp":"icp_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Problem.rank({ icp: 'icp_1' })" } } ``` Guides that call it: [What are people asking for](/start/guides/what-are-people-asking-for). # suggest URL: /business/nouns/problem/suggest · Id: `verb:Problem.suggest` · Call: `await $.Problem.suggest({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Suggest records a Customer’s ask for something the Product lacks as Evidence on a Problem, with the asker attached. Suggest records a [Customer](/business/nouns/customer)’s ask for something the [Product](/business/nouns/product) lacks as [Evidence](/business/nouns/evidence) on a [Problem](/business/nouns/problem), with the asker attached. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `text` | `text` | Yes | The ask, in the asker’s words. | | `problem` | [Problem](/business/nouns/problem) | No | The Problem it bears on; an Agent maps it when the asker names none. | | `via` | `string` | No | Where it was asked: an App, the Portal, or an Agent’s answer. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `evidence` | [Evidence](/business/nouns/evidence) | Yes | The Evidence, Opinion grade, with `askedBy` set. | | `problem` | [Problem](/business/nouns/problem) | Yes | The Problem with the new Evidence attached. | ## Effects - Emits [`Problem.suggested`](/business/events/Problem.suggested). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Raises the Evidence to Commitment when the asker reserves or pays for what they asked. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Problem.suggest](/business/nouns/problem/suggest) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Suggest the latest problem. ``` **API** ```bash curl -X POST https://api.sb/routewise.dev/problems/suggest \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"text":"Example text"}' ``` ```json { "api": "https://api.sb/routewise.dev", "evidence": { "$id": "https://api.sb/routewise.dev/evidence/evidence_1", "$type": "Evidence", "grade": "Behavior" }, "problem": { "$id": "https://api.sb/routewise.dev/problems/problem_1", "$type": "Problem", "statement": "Plans delivery routes for courier fleets through an API." }, "action": { "$id": "https://api.sb/routewise.dev/actions/action_1", "operation": "Problem.suggest", "status": "done" }, "links": { "self": "https://api.sb/routewise.dev/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { evidence, problem } = await $.Problem.suggest({ text: 'Example text' }) ``` **CLI** ```bash npx startup-builder do Problem.suggest --json '{"text":"Example text"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Problem.suggest({ text: 'Example text' })" } } ``` # enable URL: /business/nouns/process/enable · Id: `verb:Process.enable` · Call: `await $.Process.enable({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Enable turns a Process on for a Startup, so its Workflows start on their Triggers. Enable turns a [Process](/business/nouns/process) on for a [Startup](/business/nouns/startup), so its [Workflows](/business/nouns/workflow) start on their [Triggers](/business/nouns/trigger). ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `process` | [Process](/business/nouns/process) | Yes | The Process to turn on. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `process` | [Process](/business/nouns/process) | Yes | The Process, now on. | ## Effects - Emits [`Process.enabled`](/business/events/Process.enabled). - Performed by the [Founder](/agents/founding/founder). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Its Workflows start on their next Trigger; its Settings keep their inherited values until changed. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Process.enable](/business/nouns/process/enable) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Enable the latest process. ``` **API** ```bash curl -X POST https://api.sb/tutorloop.com/processes/process_1/enable \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/tutorloop.com", "process": { "$id": "https://api.sb/tutorloop.com/processes/process_1", "$type": "Process", "name": "TutorLoop" }, "action": { "$id": "https://api.sb/tutorloop.com/actions/action_1", "operation": "Process.enable", "status": "done" }, "links": { "self": "https://api.sb/tutorloop.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const process = await $.Process.enable({ process: 'process_1' }) ``` **CLI** ```bash npx startup-builder do Process.enable --json '{"process":"process_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Process.enable({ process: 'process_1' })" } } ``` Next: [`Setting.update`](/business/nouns/setting/update) (in `guide:turn-a-process-on-or-off`, `guide:chase-unpaid-invoices`, `guide:approve-card-charges-over-500` and 7 more). Guides that call it: [Turn a process on or off](/workflows/guides/turn-a-process-on-or-off), [Chase unpaid invoices](/workflows/guides/chase-unpaid-invoices), [Approve card charges over $500](/workflows/guides/approve-card-charges-over-500), [Close the books every month](/workflows/guides/close-the-books-every-month), [Pay suppliers every week](/workflows/guides/pay-suppliers-every-week) and 5 more. # Process URL: /business/nouns/process · Id: `noun:process` > A Process is a named, repeatable piece of business work, owned by a Team and run by one or more Workflows. A Process is a named, repeatable piece of business work, owned by a [Team](/business/nouns/team) and run by one or more [Workflows](/business/nouns/workflow). Each run ends in [Evidence](/business/nouns/evidence) and a [Decision](/business/nouns/decision): ship, kill, or iterate. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `name` | `string` | Yes | The name in sentence case, such as `Month-end close`. | | `status` | `string` | No | Whether the Process starts new Actions in this Startup: `off`, `on`, or `paused`. | | `says` | `text[]` | No | What a founder says to run, turn on, or ask about it. | | `settings` | `json` | No | The Settings it reads: key, type, default, the founder’s sentence and the Verb that sets each. | | `defaultOn` | `string[]` | No | The Product Templates it is on in by default. | | `wakes` | `json` | No | The Events that wake it in the Startup’s own records. | | `inputs` | `string[]` | No | The Nouns an Action reads at its start. | | `outputs` | `string[]` | No | The Nouns a finished Action leaves behind, rolled up from its Workflows. | | `outcome` | `text` | No | What a finished Action leaves true, in one sentence. | | `serviceLevel` | `json` | No | Its target duration, clock, escalation Role, and the waits that stop the clock. | | `scope` | `string` | No | Where it runs: `startup`, `studio`, or `any`. | ## Object ```json { "$id": "https://api.sb/ledgerlark.com/processes/process_1", "$type": "Process", "name": "LedgerLark", "status": "off", "says": [ "Retry failed payments" ], "settings": {}, "defaultOn": [ "saas" ], "wakes": {}, "inputs": [ "invoice" ], "outputs": [ "transaction" ], "outcome": "Each Invoice ends paid, refunded, or written off.", "serviceLevel": {}, "scope": "startup" } ``` ## Relationships - A Process **carries out** one [Play](/business/nouns/play): a Process runs the steps of a [Play](/business/nouns/play) each time the [Startup](/business/nouns/startup) runs it. `carriesOut`, inverse [`carriedOutBy`](/business/nouns/play#rel-carried-out-by). - A Process **uses** many [Workflows](/business/nouns/workflow): a Process does its work through [Workflows](/business/nouns/workflow), each the durable, executable part of the Process. `uses`, inverse [`usedIn`](/business/nouns/workflow#rel-used-in). ## Lifecycle | State | Meaning | Moves to | | --- | --- | --- | | `off` (first) | The Process starts no Actions; its Product Template does not turn it on. | `on` by [Process.enable](/business/nouns/process/enable) | | `on` | Its Workflows start on their Triggers. | `paused` by [Process.pause](/business/nouns/process/pause) | | `paused` | It starts no new Actions; Actions already in progress finish. | `on` by [Process.enable](/business/nouns/process/enable) | ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Process.enable](/business/nouns/process/enable) | Enable turns a Process on for a Startup, so its Workflows start on their Triggers. | [Founder](/agents/founding/founder) | [`Process.enabled`](/business/events/Process.enabled) | Two-way: `try`, `send`, `do` | | [Process.pause](/business/nouns/process/pause) | Pause stops a Process from starting new Actions; Actions already in progress finish. | [Founder](/agents/founding/founder) | [`Process.paused`](/business/events/Process.paused) | Two-way: `try`, `send`, `do` | | [Process.create](/business/nouns/process/create) | Creates a Process. Inherited from [Noun](/business/nouns/noun). | None. | `Process.created` | Two-way: `try`, `send`, `do` | | [Process.get](/business/nouns/process/get) | Returns one Process by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Process.list](/business/nouns/process/list) | Returns Processes, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Process.update](/business/nouns/process/update) | Changes the given properties of a Process. Inherited from [Noun](/business/nouns/noun). | None. | `Process.updated` | Two-way: `try`, `send`, `do` | | [Process.delete](/business/nouns/process/delete) | Deletes a Process; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Process.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Process.create` | Yes | Yes | Yes | No | | `Process.get` | Yes | Yes | Yes | Yes | | `Process.list` | Yes | Yes | Yes | Yes | | `Process.update` | Yes | Yes | Yes | No | | `Process.delete` | Yes | Yes | Yes | No | | `Process.enable` | Yes | Yes | Yes | No | | `Process.pause` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Enable the latest process. ``` **API** ```bash curl -X POST https://api.sb/tutorloop.com/processes/process_1/enable \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/tutorloop.com", "process": { "$id": "https://api.sb/tutorloop.com/processes/process_1", "$type": "Process", "name": "TutorLoop" }, "action": { "$id": "https://api.sb/tutorloop.com/actions/action_1", "operation": "Process.enable", "status": "done" }, "links": { "self": "https://api.sb/tutorloop.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const process = await $.Process.enable({ process: 'process_1' }) ``` **CLI** ```bash npx startup-builder do Process.enable --json '{"process":"process_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Process.enable({ process: 'process_1' })" } } ``` ## Example Billing is a Process owned by the [Finance Team](/agents/finance). The [Dunning](/workflows/processes/billing/dunning) and monthly close Workflows run it, and its loop measures revenue recovered within 30 days of a failed charge. # pause URL: /business/nouns/process/pause · Id: `verb:Process.pause` · Call: `await $.Process.pause({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Pause stops a Process from starting new Actions; Actions already in progress finish. Pause stops a [Process](/business/nouns/process) from starting new [Actions](/business/nouns/action); Actions already in progress finish. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `process` | [Process](/business/nouns/process) | Yes | The Process to pause. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `process` | [Process](/business/nouns/process) | Yes | The paused Process. | ## Effects - Emits [`Process.paused`](/business/events/Process.paused). - Performed by the [Founder](/agents/founding/founder). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Holds its Triggers until the Process is enabled again. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Process.pause](/business/nouns/process/pause) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Pause the latest process. ``` **API** ```bash curl -X POST https://api.sb/shiftnote.app/processes/process_1/pause \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/shiftnote.app", "process": { "$id": "https://api.sb/shiftnote.app/processes/process_1", "$type": "Process", "name": "ShiftNote" }, "action": { "$id": "https://api.sb/shiftnote.app/actions/action_1", "operation": "Process.pause", "status": "done" }, "links": { "self": "https://api.sb/shiftnote.app/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const process = await $.Process.pause({ process: 'process_1' }) ``` **CLI** ```bash npx startup-builder do Process.pause --json '{"process":"process_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Process.pause({ process: 'process_1' })" } } ``` # Product Template URL: /business/nouns/product-template · Id: `noun:product-template` > A Product Template is a reusable definition of one kind of Product: what it sells, who supplies the work, who buys, and how it earns. A Product Template is a reusable definition of one kind of [Product](/business/nouns/product): what it sells, who supplies the work, who buys, and how it earns. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `slug` | `string` | Yes | The page path under `/start/templates/products`. | | `kind` | `string` | Yes | The abstract Product: `data`, `software`, `agent`, or `service`. | | `supply` | `string` | Yes | Who supplies the work: `digital`, which is unlimited, or `human`, which is recruited and credentialed. | | `worker` | `string` | Yes | Who does the work: `agents`, `humans`, or `agents-and-humans`. | | `buyer` | `string` | Yes | Who buys: `human`, `agent`, or `human-or-agent`. | | `earningModel` | `string` | Yes | How it earns: `subscription`, `usage`, `commerce`, `marketplace`, or `directory`. | | `assurance` | `text` | No | What the buyer can rely on, in one sentence. | ## Object ```json { "$id": "https://api.sb/kilnbakery.com/product-templates/product_template_1", "$type": "ProductTemplate", "slug": "kiln-bakery", "kind": "data", "supply": "Example supply", "worker": "agents", "buyer": "human", "earningModel": "subscription", "assurance": "Example assurance" } ``` ## Relationships - A Product Template **is built from** many [Product Templates](/business/nouns/product-template): a Product Template built on others, such as a [Service](/business/nouns/service) run on [Software](/business/nouns/software), inherits their coverage, cost and assurance. `builtFrom`, inverse `underlies`. - A Product Template **is combined in** many [Startup Templates](/business/nouns/startup-template): a [Startup Template](/business/nouns/startup-template) combines one or more Product Templates, each one kind of [Product](/business/nouns/product) its [Startups](/business/nouns/startup) sell. `combinedIn`, inverse [`combines`](/business/nouns/startup-template#rel-combines). - A Product Template **underlies** many [Product Templates](/business/nouns/product-template): a Product Template built on others, such as a [Service](/business/nouns/service) run on [Software](/business/nouns/software), inherits their coverage, cost and assurance. `underlies`, inverse `builtFrom`. ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [ProductTemplate.create](/business/nouns/product-template/create) | Creates a Product Template. Inherited from [Noun](/business/nouns/noun). | None. | `ProductTemplate.created` | Two-way: `try`, `send`, `do` | | [ProductTemplate.get](/business/nouns/product-template/get) | Returns one Product Template by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [ProductTemplate.list](/business/nouns/product-template/list) | Returns Product Templates, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [ProductTemplate.update](/business/nouns/product-template/update) | Changes the given properties of a Product Template. Inherited from [Noun](/business/nouns/noun). | None. | `ProductTemplate.updated` | Two-way: `try`, `send`, `do` | | [ProductTemplate.delete](/business/nouns/product-template/delete) | Deletes a Product Template; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `ProductTemplate.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `ProductTemplate.create` | Yes | Yes | Yes | No | | `ProductTemplate.get` | Yes | Yes | Yes | Yes | | `ProductTemplate.list` | Yes | Yes | Yes | Yes | | `ProductTemplate.update` | Yes | Yes | Yes | No | | `ProductTemplate.delete` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Add a product template to RouteWise. ``` **API** ```bash curl -X POST https://api.sb/routewise.dev/product-templates \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"slug":"route-wise","kind":"data","supply":"Example supply","worker":"agents","buyer":"human","earningModel":"subscription"}' ``` ```json { "api": "https://api.sb/routewise.dev", "productTemplate": { "$id": "https://api.sb/routewise.dev/product-templates/product_template_1", "$type": "ProductTemplate", "slug": "route-wise", "kind": "data", "supply": "Example supply", "worker": "agents" }, "action": { "$id": "https://api.sb/routewise.dev/actions/action_1", "operation": "ProductTemplate.create", "status": "done" }, "links": { "self": "https://api.sb/routewise.dev/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const productTemplate = await $.ProductTemplate.create({ slug: 'route-wise', kind: 'data', supply: 'Example supply', worker: 'agents', buyer: 'human', earningModel: 'subscription' }) ``` **CLI** ```bash npx startup-builder do ProductTemplate.create --json '{"slug":"route-wise","kind":"data","supply":"Example supply","worker":"agents","buyer":"human","earningModel":"subscription"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.ProductTemplate.create({ slug: 'route-wise', kind: 'data', supply: 'Example supply', worker: 'agents', buyer: 'human', earningModel: 'subscription' })" } } ``` ## Example The [SaaS](/products/templates/saas) Product Template gives a new invoice-tracking app its [Nouns](/business/nouns/noun), [Verbs](/business/nouns/verb), [Interfaces](/business/nouns/interface), [Pages](/business/nouns/page) and default [Offers](/business/nouns/offer). The [Startup](/business/nouns/startup) changes only its [Problem](/business/nouns/problem), [Price](/business/nouns/price) and data. # Product URL: /business/nouns/product · Id: `noun:product` > A Product is what a Customer gets from a Startup, with a promise the Customer can rely on. A Product is what a [Customer](/business/nouns/customer) gets from a [Startup](/business/nouns/startup), with a promise the Customer can rely on. An [Offer](/business/nouns/offer) sells it at a [Price](/business/nouns/price); the Product itself carries none. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `name` | `string` | Yes | The name of the Product. | | `promise` | `text` | Yes | What the Customer can rely on. | | `status` | `string` | Yes | One of `draft`, `selling` or `retired`, set by its Offers. | ## Object ```json { "$id": "https://api.sb/routewise.dev/products/product_1", "$type": "Product", "name": "RouteWise", "promise": "A route plan for 500 stops in under two seconds.", "status": "draft" } ``` ## Relationships - A Product **builds into** many [Products](/business/nouns/product): a Product composes other Products; a change to a part reaches every Product built from it. `buildsInto`, inverse `builtFrom`. - A Product **is built from** many [Products](/business/nouns/product): a Product composes other Products; a change to a part reaches every Product built from it. `builtFrom`, inverse `buildsInto`. - A Product **draws on** many [Sources](/business/nouns/source): a Product keeps its promise with [Sources](/business/nouns/source) it did not build: owned, wrapped, or recruited. `drawsOn`, inverse [`supplies`](/business/nouns/source#rel-supplies). - A Product **has** many [Implementations](/business/nouns/implementation): an [Implementation](/business/nouns/implementation) runs an [Interface](/business/nouns/interface), [System](/business/nouns/system) or [Verb](/business/nouns/verb) of one Product. `implementations`, inverse [`runs`](/business/nouns/implementation#rel-runs). - A Product **is included in** many [Offers](/business/nouns/offer): each [Offer](/business/nouns/offer) sells one Product; one Product sits inside many Offers at different prices and terms. `includedIn`, inverse [`includes`](/business/nouns/offer#rel-includes). - A Product **is made by** one [Startup](/business/nouns/startup): each Product belongs to exactly one [Startup](/business/nouns/startup), which builds it and stands behind its promise. `madeBy`, inverse [`makes`](/business/nouns/startup#rel-makes). - A Product **has** one [Publication](/business/nouns/publication): a Product reaches its [Customers](/business/nouns/customer) through one [Publication](/business/nouns/publication); nothing inside it names the platform. `publication`, inverse [`publishes`](/business/nouns/publication#rel-publishes). - A Product **is reached via** many [Interfaces](/business/nouns/interface): each [Interface](/business/nouns/interface) exposes one Product; a Product is reached through many Interfaces. `reachedVia`, inverse [`reaches`](/business/nouns/interface#rel-reaches). ## Lifecycle | State | Meaning | Moves to | | --- | --- | --- | | `draft` (first) | Defined, with no published Offer selling it. | `selling` on [`Offer.published`](/business/events/Offer.published) when the Offer is the first published Offer on this Product | | `selling` | At least one published Offer sells it. | `retired` on [`Offer.withdrawn`](/business/events/Offer.withdrawn) when the last published Offer on this Product is withdrawn | | `retired` | No published Offer sells it; Customers keep what their Orders and Subscriptions bought. | `selling` on [`Offer.published`](/business/events/Offer.published) when an Offer on this Product is published again | ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Product.create](/business/nouns/product/create) | Creates a Product. Inherited from [Noun](/business/nouns/noun). | None. | `Product.created` | Two-way: `try`, `send`, `do` | | [Product.get](/business/nouns/product/get) | Returns one Product by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Product.list](/business/nouns/product/list) | Returns Products, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Product.update](/business/nouns/product/update) | Changes the given properties of a Product. Inherited from [Noun](/business/nouns/noun). | None. | `Product.updated` | Two-way: `try`, `send`, `do` | | [Product.delete](/business/nouns/product/delete) | Deletes a Product; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Product.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Product.create` | Yes | Yes | Yes | No | | `Product.get` | Yes | Yes | Yes | Yes | | `Product.list` | Yes | Yes | Yes | Yes | | `Product.update` | Yes | Yes | Yes | No | | `Product.delete` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Add a product to LedgerLark. ``` **API** ```bash curl -X POST https://api.sb/ledgerlark.com/products \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"name":"LedgerLark","promise":"Books closed by the fifth of each month."}' ``` ```json { "api": "https://api.sb/ledgerlark.com", "product": { "$id": "https://api.sb/ledgerlark.com/products/product_1", "$type": "Product", "name": "LedgerLark", "promise": "Books closed by the fifth of each month.", "status": "draft" }, "action": { "$id": "https://api.sb/ledgerlark.com/actions/action_1", "operation": "Product.create", "status": "done" }, "links": { "self": "https://api.sb/ledgerlark.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const product = await $.Product.create({ name: 'LedgerLark', promise: 'Books closed by the fifth of each month.' }) ``` **CLI** ```bash npx startup-builder do Product.create --json '{"name":"LedgerLark","promise":"Books closed by the fifth of each month."}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Product.create({ name: 'LedgerLark', promise: 'Books closed by the fifth of each month.' })" } } ``` ## Example A certified translation is a Product whose `promise` reads "accepted by the receiving agency within 48 hours, or redone free." Two Offers sell it: $40 a page, and $300 a month for 10 pages. # Project URL: /business/nouns/project · Id: `noun:project` > A Project is a body of work toward a Goal: its Tasks and Issues, a start, and a target date. A Project is a body of work toward a [Goal](/business/nouns/goal): its [Tasks](/business/nouns/task) and [Issues](/business/nouns/issue), a start, and a target date. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `startsOn` | `date` | No | When work begins. | | `targetDate` | `date` | No | When it should be done. | ## Object ```json { "$id": "https://api.sb/shiftnote.app/projects/project_1", "$type": "Project", "startsOn": "2026-10-22", "targetDate": "2026-10-22" } ``` ## Relationships - A Project **advances** one [Goal](/business/nouns/goal): a Project’s work serves one [Goal](/business/nouns/goal). `advances`, inverse [`projects`](/business/nouns/goal#rel-projects). - A Project **plans** many [Tasks](/business/nouns/task): a Project is made of [Tasks](/business/nouns/task). `plans`, inverse [`project`](/business/nouns/task#rel-project). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Project.create](/business/nouns/project/create) | Creates a Project. Inherited from [Noun](/business/nouns/noun). | None. | `Project.created` | Two-way: `try`, `send`, `do` | | [Project.get](/business/nouns/project/get) | Returns one Project by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Project.list](/business/nouns/project/list) | Returns Projects, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Project.update](/business/nouns/project/update) | Changes the given properties of a Project. Inherited from [Noun](/business/nouns/noun). | None. | `Project.updated` | Two-way: `try`, `send`, `do` | | [Project.delete](/business/nouns/project/delete) | Deletes a Project; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Project.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Project.create` | Yes | Yes | Yes | No | | `Project.get` | Yes | Yes | Yes | Yes | | `Project.list` | Yes | Yes | Yes | Yes | | `Project.update` | Yes | Yes | Yes | No | | `Project.delete` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Add a project to RouteWise. ``` **API** ```bash curl -X POST https://api.sb/routewise.dev/projects \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"startsOn":"2026-10-22"}' ``` ```json { "api": "https://api.sb/routewise.dev", "project": { "$id": "https://api.sb/routewise.dev/projects/project_1", "$type": "Project", "startsOn": "2026-10-22", "targetDate": "2026-10-22" }, "action": { "$id": "https://api.sb/routewise.dev/actions/action_1", "operation": "Project.create", "status": "done" }, "links": { "self": "https://api.sb/routewise.dev/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const project = await $.Project.create({ startsOn: '2026-10-22' }) ``` **CLI** ```bash npx startup-builder do Project.create --json '{"startsOn":"2026-10-22"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Project.create({ startsOn: '2026-10-22' })" } } ``` ## Example A tax-preparation service opens a second state as a Project. It holds 22 [Tasks](/business/nouns/task) and 4 [Issues](/business/nouns/issue), starts on the 1st, and targets a date eight weeks later. # Proof URL: /business/nouns/proof · Id: `noun:proof` > A Proof is the sealed result of one Control test: the Events it read, the root it checked them against, and every exception. A Proof is the sealed result of one [Control](/business/nouns/control) test: the [Events](/business/nouns/event) it read, the root it checked them against, and every exception. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `control` | [Control](/business/nouns/control) | Yes | The Control whose test ran. | | `namespace` | `string` | Yes | The Startup, Studio, or platform namespace the test read. | | `from` | `datetime` | Yes | The start of the range tested. | | `to` | `datetime` | Yes | The end of the range tested. | | `root` | `string` | Yes | The published log root the selected Events roll up to. | | `count` | `integer` | Yes | How many Events the test read. | | `exceptions` | `integer` | Yes | How many failed the assertion; each opens an Issue. | ## Object ```json { "$id": "https://api.sb/kilnbakery.com/proofs/proof_1", "$type": "Proof", "control": "control_1", "namespace": "Example namespace", "from": "2026-10-22T12:00:00Z", "to": "2026-10-22T12:00:00Z", "root": "Example root", "count": 1, "exceptions": 1 } ``` ## Relationships - A Proof **proves** one [Control](/business/nouns/control): the [Control](/business/nouns/control) whose test the Proof records running over a range of [Events](/business/nouns/event). `proves`, inverse [`provenBy`](/business/nouns/control#rel-proven-by). - A Proof **is relied on by** many [Audits](/business/nouns/audit): the Proofs the auditing firm samples across the report period. `reliedOnBy`, inverse [`reliesOn`](/business/nouns/audit#rel-relies-on). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Proof.get](/business/nouns/proof/get) | Returns one Proof by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Proof.list](/business/nouns/proof/list) | Returns Proofs, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | A Proof is kept forever and never edited: it has no `update` or `delete`. ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Proof.get` | Yes | Yes | Yes | Yes | | `Proof.list` | Yes | Yes | Yes | Yes | ## Call it **Ask** ```text Show me the latest proof. ``` **API** ```bash curl https://api.sb/quietcopy.com/proofs/proof_1 \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/quietcopy.com", "$type": "Proof", "$id": "https://api.sb/quietcopy.com/proofs/proof_1", "proof": { "$id": "https://api.sb/quietcopy.com/proofs/proof_1", "$type": "Proof", "control": "control_1", "namespace": "Example namespace", "from": "2026-10-22T12:00:00Z", "to": "2026-10-22T12:00:00Z" }, "links": { "self": "https://api.sb/quietcopy.com/proofs/proof_1", "up": "https://api.sb/quietcopy.com/proofs" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const proof = await $.Proof.get({ id: 'proof_1' }) ``` **CLI** ```bash npx startup-builder do Proof.get --json '{"id":"proof_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Proof.get({ id: 'proof_1' })" } } ``` ## Example Each night, the [Permission decay](/systems/trust-and-governance/controls/permission-decay) test for a recipe planner reads 4,812 [Events](/business/nouns/event). It finds 0 exceptions and seals a Proof citing the published root. # engage URL: /business/nouns/prospect/engage · Id: `verb:Prospect.engage` · Call: `await $.Prospect.engage({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Engage records a Prospect’s first reply or raised hand and makes it a Lead that keeps its Acquisition. Engage records a [Prospect](/business/nouns/prospect)’s first reply or raised hand and makes it a [Lead](/business/nouns/lead) that keeps its [Acquisition](/business/nouns/acquisition). ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `prospect` | [Prospect](/business/nouns/prospect) | Yes | The Prospect that replied or raised a hand. | | `message` | [Message](/business/nouns/message) | No | The reply or Form submission that shows the engagement. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `lead` | [Lead](/business/nouns/lead) | Yes | The new Lead, with status `new` and the Prospect’s Acquisition. | | `prospect` | [Prospect](/business/nouns/prospect) | Yes | The Prospect who engaged. | ## Effects - Emits [`Prospect.engaged`](/business/events/Prospect.engaged). - Performed by the [Prospector](/agents/sales/prospector). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Ends outreach to the Prospect: no further Sequence step sends. - Links the Lead to the Prospect’s Acquisition. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Prospect.engage](/business/nouns/prospect/engage) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Engage the prospect Priya Natarajan. ``` **API** ```bash curl -X POST https://api.sb/ledgerlark.com/prospects/prospect_1/engage \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/ledgerlark.com", "lead": { "$id": "https://api.sb/ledgerlark.com/leads/lead_1", "$type": "Lead", "status": "new" }, "prospect": { "$id": "https://api.sb/ledgerlark.com/prospects/prospect_1", "$type": "Prospect", "foundIn": "Example found in", "basis": "Example basis" }, "action": { "$id": "https://api.sb/ledgerlark.com/actions/action_1", "operation": "Prospect.engage", "status": "done" }, "links": { "self": "https://api.sb/ledgerlark.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { lead, prospect } = await $.Prospect.engage({ prospect: 'prospect_1' }) ``` **CLI** ```bash npx startup-builder do Prospect.engage --json '{"prospect":"prospect_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Prospect.engage({ prospect: 'prospect_1' })" } } ``` # Prospect URL: /business/nouns/prospect · Id: `noun:prospect` > A Prospect is a person or Organization a Startup found but who has never engaged, held with the legal basis for contact. A Prospect is a person or [Organization](/business/nouns/organization) a [Startup](/business/nouns/startup) found but who has never engaged, held with the legal basis for contact. Its first reply [engages](/business/nouns/prospect/engage) it, which makes it a [Lead](/business/nouns/lead). ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `foundIn` | `string` | Yes | Where the Startup found them. | | `basis` | `string` | Yes | The legal basis for contacting them. | ## Object ```json { "$id": "https://api.sb/petpantry.shop/prospects/prospect_1", "$type": "Prospect", "foundIn": "Example found in", "basis": "Example basis" } ``` ## Relationships - A Prospect **is acquired by** one [Acquisition](/business/nouns/acquisition): a Prospect’s [Acquisition](/business/nouns/acquisition) names the outbound [Play](/business/nouns/play) and [Mailbox](/business/nouns/mailbox) that first reached it. `acquiredBy`, inverse [`prospects`](/business/nouns/acquisition#rel-prospects). - A Prospect **converts to** one [Lead](/business/nouns/lead): a Prospect becomes a [Lead](/business/nouns/lead) on first engaging, such as a reply or a [Form](/business/nouns/form) submission. `convertsTo`, inverse [`convertedFrom`](/business/nouns/lead#rel-converted-from). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Prospect.engage](/business/nouns/prospect/engage) | Engage records a Prospect’s first reply or raised hand and makes it a Lead that keeps its Acquisition. | [Prospector](/agents/sales/prospector) | [`Prospect.engaged`](/business/events/Prospect.engaged) | Two-way: `try`, `send`, `do` | | [Prospect.create](/business/nouns/prospect/create) | Creates a Prospect. Inherited from [Noun](/business/nouns/noun). | None. | `Prospect.created` | Two-way: `try`, `send`, `do` | | [Prospect.get](/business/nouns/prospect/get) | Returns one Prospect by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Prospect.list](/business/nouns/prospect/list) | Returns Prospects, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Prospect.update](/business/nouns/prospect/update) | Changes the given properties of a Prospect. Inherited from [Noun](/business/nouns/noun). | None. | `Prospect.updated` | Two-way: `try`, `send`, `do` | | [Prospect.delete](/business/nouns/prospect/delete) | Deletes a Prospect; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Prospect.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Prospect.create` | Yes | Yes | Yes | No | | `Prospect.get` | Yes | Yes | Yes | Yes | | `Prospect.list` | Yes | Yes | Yes | Yes | | `Prospect.update` | Yes | Yes | Yes | No | | `Prospect.delete` | Yes | Yes | Yes | No | | `Prospect.engage` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Engage the prospect Priya Natarajan. ``` **API** ```bash curl -X POST https://api.sb/ledgerlark.com/prospects/prospect_1/engage \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/ledgerlark.com", "lead": { "$id": "https://api.sb/ledgerlark.com/leads/lead_1", "$type": "Lead", "status": "new" }, "prospect": { "$id": "https://api.sb/ledgerlark.com/prospects/prospect_1", "$type": "Prospect", "foundIn": "Example found in", "basis": "Example basis" }, "action": { "$id": "https://api.sb/ledgerlark.com/actions/action_1", "operation": "Prospect.engage", "status": "done" }, "links": { "self": "https://api.sb/ledgerlark.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { lead, prospect } = await $.Prospect.engage({ prospect: 'prospect_1' }) ``` **CLI** ```bash npx startup-builder do Prospect.engage --json '{"prospect":"prospect_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Prospect.engage({ prospect: 'prospect_1' })" } } ``` ## Example A litigation-support firm found on a public list of court vendors becomes a Prospect, held with legitimate interest as the basis for one outreach email. # Publication URL: /business/nouns/publication · Id: `noun:publication` > A Publication is the branded package a Startup’s Customers use: Domain, Interfaces, packages, docs and Portal, compiled from its Brand and a Version. A Publication is the branded package a [Startup](/business/nouns/startup)’s [Customers](/business/nouns/customer) use: [Domain](/business/nouns/domain), [Interfaces](/business/nouns/interface), packages, docs and [Portal](/business/nouns/portal), compiled from its [Brand](/business/nouns/brand) and a [Version](/business/nouns/version). Nothing inside it names the platform. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `brand` | [Brand](/business/nouns/brand) | Yes | The Brand every surface carries. | | `version` | [Version](/business/nouns/version) | Yes | The Version it compiles from; a restyle compiles a new Publication and leaves the API version alone. | | `domain` | [Domain](/business/nouns/domain) | Yes | The canonical Domain every surface answers on. | | `api` | `url` | Yes | Where the API answers: `/api` on the Domain. `api.` on the Domain is an alias that serves the same API. | | `mcp` | `url` | Yes | Where the MCP server answers: `/mcp` on the Domain. | | `docs` | `url` | Yes | The docs, with `llms.txt` and Markdown per page. | | `statusPage` | `url` | No | The status page, with every Incident that touched an Interface. | | `portal` | `url` | No | The Portal, where a Customer manages keys, usage, billing and Tenant settings. | | `packages` | `json` | No | The SDK, CLI and MCP package names, one per language and package registry. | | `keyPrefix` | `string` | No | The Brand prefix on every API key, ahead of the fixed pattern secret scanners match. | | `envPrefix` | `string` | No | The prefix of the key variable the SDK and CLI read, such as `TRANSCRIBE_API_KEY`. | | `webhookHeader` | `string` | No | The signature header on every webhook delivery to a Customer. | | `errorNamespace` | `url` | No | The base of every error `type` a Customer reads, on the Domain. | ## Object ```json { "$id": "https://api.sb/petpantry.shop/publications/publication_1", "$type": "Publication", "brand": "brand_1", "version": "version_1", "domain": "domain_1", "api": "https://transcribe.fm/api", "mcp": "https://transcribe.fm/mcp", "docs": "https://transcribe.fm/docs", "statusPage": "https://transcribe.fm/status", "portal": "https://transcribe.fm/portal", "packages": { "npm": "transcribe", "pypi": "transcribe" }, "keyPrefix": "transcribe_sk_live_", "envPrefix": "TRANSCRIBE_", "webhookHeader": "Transcribe-Signature", "errorNamespace": "https://transcribe.fm/errors" } ``` ## Relationships - A Publication **publishes** one [Product](/business/nouns/product): a [Product](/business/nouns/product) reaches its [Customers](/business/nouns/customer) through one Publication; nothing inside it names the platform. `publishes`, inverse [`publication`](/business/nouns/product#rel-publication). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Publication.get](/business/nouns/publication/get) | Returns one Publication by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Publication.list](/business/nouns/publication/list) | Returns Publications, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | A Publication is kept forever and never edited: it has no `update` or `delete`. ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Publication.get` | Yes | Yes | Yes | Yes | | `Publication.list` | Yes | Yes | Yes | Yes | ## Call it **Ask** ```text Show me the latest publication. ``` **API** ```bash curl https://api.sb/tutorloop.com/publications/publication_1 \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/tutorloop.com", "$type": "Publication", "$id": "https://api.sb/tutorloop.com/publications/publication_1", "publication": { "$id": "https://api.sb/tutorloop.com/publications/publication_1", "$type": "Publication", "brand": "brand_1", "version": "version_1", "domain": "domain_1", "api": "https://transcribe.fm/api" }, "links": { "self": "https://api.sb/tutorloop.com/publications/publication_1", "up": "https://api.sb/tutorloop.com/publications" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const publication = await $.Publication.get({ id: 'publication_1' }) ``` **CLI** ```bash npx startup-builder do Publication.get --json '{"id":"publication_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Publication.get({ id: 'publication_1' })" } } ``` ## Example ```json { "$id": "https://api.sb/transcribe.fm/publications/publication_1", "$type": "Publication", "domain": "domain_1", "api": "https://transcribe.fm/api", "mcp": "https://transcribe.fm/mcp", "docs": "https://transcribe.fm/docs", "statusPage": "https://transcribe.fm/status", "portal": "https://transcribe.fm/portal", "packages": { "npm": "transcribe", "pypi": "transcribe" }, "keyPrefix": "transcribe_sk_live_", "envPrefix": "TRANSCRIBE_", "webhookHeader": "Transcribe-Signature", "errorNamespace": "https://transcribe.fm/errors" } ``` # Purpose URL: /business/nouns/purpose · Id: `noun:purpose` > A Purpose is a named reason personal data is processed, with a lawful basis per jurisdiction. A Purpose is a named reason personal data is processed, with a lawful basis per jurisdiction. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `name` | `string` | Yes | The reason, such as marketing email or call recording. | ## Object ```json { "$id": "https://api.sb/kilnbakery.com/purposes/purpose_1", "$type": "Purpose", "name": "Kiln Bakery" } ``` ## Relationships - A Purpose **has** many [Consents](/business/nouns/consent): the Purpose the [Consent](/business/nouns/consent) permits processing for, and nothing beyond it. `consents`, inverse [`covers`](/business/nouns/consent#rel-covers). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Purpose.create](/business/nouns/purpose/create) | Creates a Purpose. Inherited from [Noun](/business/nouns/noun). | None. | `Purpose.created` | Two-way: `try`, `send`, `do` | | [Purpose.get](/business/nouns/purpose/get) | Returns one Purpose by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Purpose.list](/business/nouns/purpose/list) | Returns Purposes, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Purpose.update](/business/nouns/purpose/update) | Changes the given properties of a Purpose. Inherited from [Noun](/business/nouns/noun). | None. | `Purpose.updated` | Two-way: `try`, `send`, `do` | | [Purpose.delete](/business/nouns/purpose/delete) | Deletes a Purpose; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Purpose.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Purpose.create` | Yes | Yes | Yes | No | | `Purpose.get` | Yes | Yes | Yes | Yes | | `Purpose.list` | Yes | Yes | Yes | Yes | | `Purpose.update` | Yes | Yes | Yes | No | | `Purpose.delete` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Add a purpose to PetPantry. ``` **API** ```bash curl -X POST https://api.sb/petpantry.shop/purposes \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"name":"PetPantry"}' ``` ```json { "api": "https://api.sb/petpantry.shop", "purpose": { "$id": "https://api.sb/petpantry.shop/purposes/purpose_1", "$type": "Purpose", "name": "PetPantry" }, "action": { "$id": "https://api.sb/petpantry.shop/actions/action_1", "operation": "Purpose.create", "status": "done" }, "links": { "self": "https://api.sb/petpantry.shop/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const purpose = await $.Purpose.create({ name: 'PetPantry' }) ``` **CLI** ```bash npx startup-builder do Purpose.create --json '{"name":"PetPantry"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Purpose.create({ name: 'PetPantry' })" } } ``` ## Example "Send product updates" is a Purpose with consent as its lawful basis. "[Bill](/business/nouns/bill) the [Customer](/business/nouns/customer)" is a Purpose with contract as its basis. # Question URL: /business/nouns/question · Id: `noun:question` > A Question is what a pending Action asks a Party, a Role, or a Worker before it resumes, kept on the Action with its answer. A Question is what a [Worker](/business/nouns/worker) asks a [Party](/business/nouns/party) during an [Action](/business/nouns/action), with choices or a schema, and its answer resumes the Action. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `to` | [Thing](/business/nouns/thing) | Yes | Who is asked: a Party such as the Customer or the caller, a Role, or a Worker. | | `text` | `text` | Yes | The question, in one message. | | `choices` | `string[]` | No | The answers offered, rendered as a picker; free text when absent. | | `schema` | `json` | No | The typed answer’s shape, rendered as form fields in the Portal. | | `answerBy` | `datetime` | No | After this, the Action’s timeout rule applies. | | `answer` | `json` | No | The answer given, with who gave it and through which Interface. | | `answeredAt` | `datetime` | No | When the answer arrived; the Action resumes then. | ## Object ```json { "$id": "https://api.sb/petpantry.shop/questions/question_1", "$type": "Question", "to": "thing_1", "text": "Example text", "choices": [ "Example choices" ], "schema": {}, "answerBy": "2026-10-22T12:00:00Z", "answer": {}, "answeredAt": "2026-10-22T12:00:00Z" } ``` ## Relationships - A Question **has** one [Action](/business/nouns/action): a pending [Action](/business/nouns/action) asks Questions and waits `awaitingInput` until each is answered or its deadline passes. `action`, inverse [`asks`](/business/nouns/action#rel-asks). - A Question **is posted in** one [Thread](/business/nouns/thread): each Question posts in the [Thread](/business/nouns/thread) of the record it concerns, where free-text replies land. `postedIn`, inverse [`questions`](/business/nouns/thread#rel-questions). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Question.get](/business/nouns/question/get) | Returns one Question by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Question.list](/business/nouns/question/list) | Returns Questions, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | A Question is kept forever and never edited: it has no `update` or `delete`. ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Question.get` | Yes | Yes | Yes | Yes | | `Question.list` | Yes | Yes | Yes | Yes | ## Call it **Ask** ```text Show me the latest question. ``` **API** ```bash curl https://api.sb/tutorloop.com/questions/question_1 \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/tutorloop.com", "$type": "Question", "$id": "https://api.sb/tutorloop.com/questions/question_1", "question": { "$id": "https://api.sb/tutorloop.com/questions/question_1", "$type": "Question", "to": "thing_1", "text": "Example text" }, "links": { "self": "https://api.sb/tutorloop.com/questions/question_1", "up": "https://api.sb/tutorloop.com/questions" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const question = await $.Question.get({ id: 'question_1' }) ``` **CLI** ```bash npx startup-builder do Question.get --json '{"id":"question_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Question.get({ id: 'question_1' })" } } ``` ## Example `patentpad.com`'s drafting [Agent](/business/nouns/agent) asks a [Customer](/business/nouns/customer) which of two inventions to claim, with three choices and an `answerBy` two days out. The Customer taps one in the [Portal](/business/nouns/portal), and the draft resumes. # accept URL: /business/nouns/quote/accept · Id: `verb:Quote.accept` · Call: `await $.Quote.accept({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Accept takes a sent Quote before it expires, turning one-time lines into an Order and recurring lines into a Subscription. Accept takes a sent [Quote](/business/nouns/quote) before it expires, turning one-time lines into an [Order](/business/nouns/order) and recurring lines into a [Subscription](/business/nouns/subscription). ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `quote` | [Quote](/business/nouns/quote) | Yes | The sent Quote. | | `party` | [Party](/business/nouns/party) | Yes | The Contact or Organization accepting, who becomes the Customer. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `order` | [Order](/business/nouns/order) | No | The Order for the one-time lines, when the Quote has any. | | `subscription` | [Subscription](/business/nouns/subscription) | No | The Subscription for the recurring lines, at each line’s quantity and term. | | `quote` | [Quote](/business/nouns/quote) | Yes | The Quote, now accepted. | ## Effects - Emits [`Quote.accepted`](/business/events/Quote.accepted). - Performed by the [Sales Engineer](/agents/sales/sales-engineer). - One-way: it waits out its delay window, and runs in the `send` and `do` modes. - Runs `Offer.accept` for each quoted Offer, pinning its Version at the quoted terms. - Carries each line’s discount and the payment terms onto the Order or Subscription and their Invoices. - Wins the Deal that issued the Quote and supersedes every other open Quote on it. - A Service Order enters intake and authorizes payment; its Outcome Contract’s `earns` Event captures it. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Quote.accept](/business/nouns/quote/accept) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Medium: one-way, bounded | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | 1 business hour, in which a watcher can pause, redirect or cancel it; then it runs. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Accept the latest quote with a party. ``` **API** ```bash curl -X POST https://api.sb/quietcopy.com/quotes/quote_1/accept \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"party":"party_1"}' ``` ```json { "api": "https://api.sb/quietcopy.com", "order": { "$id": "https://api.sb/quietcopy.com/orders/order_1", "$type": "Order", "total": { "amount": 39, "currency": "USD" }, "status": "placed" }, "subscription": { "$id": "https://api.sb/quietcopy.com/subscriptions/subscription_1", "$type": "Subscription", "status": "active" }, "quote": { "$id": "https://api.sb/quietcopy.com/quotes/quote_1", "$type": "Quote", "total": { "amount": 39, "currency": "USD" }, "validUntil": "2026-10-22", "status": "accepted", "lines": {} }, "action": { "$id": "https://api.sb/quietcopy.com/actions/action_1", "operation": "Quote.accept", "status": "done" }, "links": { "self": "https://api.sb/quietcopy.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { order, subscription, quote } = await $.Quote.accept({ quote: 'quote_1', party: 'party_1' }) ``` **CLI** ```bash npx startup-builder do Quote.accept --json '{"quote":"quote_1","party":"party_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Quote.accept({ quote: 'quote_1', party: 'party_1' })" } } ``` # decline URL: /business/nouns/quote/decline · Id: `verb:Quote.decline` · Call: `await $.Quote.decline({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Decline records the buyer’s refusal of a sent Quote, with the reason in their words. Decline records the buyer’s refusal of a sent [Quote](/business/nouns/quote), with the reason in their words. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `quote` | [Quote](/business/nouns/quote) | Yes | The sent Quote. | | `reason` | `text` | No | Why the buyer declined, kept verbatim. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `quote` | [Quote](/business/nouns/quote) | Yes | The declined Quote. | ## Effects - Emits [`Quote.declined`](/business/events/Quote.declined). - Performed by the [Sales Engineer](/agents/sales/sales-engineer). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Records the reason as Evidence on the Deal; the Deal stays open for a superseding Quote. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Quote.decline](/business/nouns/quote/decline) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Decline the latest quote. ``` **API** ```bash curl -X POST https://api.sb/tutorloop.com/quotes/quote_1/decline \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/tutorloop.com", "quote": { "$id": "https://api.sb/tutorloop.com/quotes/quote_1", "$type": "Quote", "total": { "amount": 60, "currency": "USD" }, "validUntil": "2026-10-22", "status": "declined", "lines": {} }, "action": { "$id": "https://api.sb/tutorloop.com/actions/action_1", "operation": "Quote.decline", "status": "done" }, "links": { "self": "https://api.sb/tutorloop.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const quote = await $.Quote.decline({ quote: 'quote_1' }) ``` **CLI** ```bash npx startup-builder do Quote.decline --json '{"quote":"quote_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Quote.decline({ quote: 'quote_1' })" } } ``` # expire URL: /business/nouns/quote/expire · Id: `verb:Quote.expire` · Call: `await $.Quote.expire({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Expire closes a sent Quote that reached its validUntil date unaccepted; it never converts afterward. Expire closes a sent [Quote](/business/nouns/quote) that reached its validUntil date unaccepted; it never converts afterward. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `quote` | [Quote](/business/nouns/quote) | Yes | The Quote past its date. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `quote` | [Quote](/business/nouns/quote) | Yes | The expired Quote. | ## Effects - Emits [`Quote.expired`](/business/events/Quote.expired). - Performed by the [Sales Engineer](/agents/sales/sales-engineer). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Runs on the validUntil date with no caller. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Quote.expire](/business/nouns/quote/expire) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Expire the latest quote. ``` **API** ```bash curl -X POST https://api.sb/routewise.dev/quotes/quote_1/expire \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/routewise.dev", "quote": { "$id": "https://api.sb/routewise.dev/quotes/quote_1", "$type": "Quote", "total": { "amount": 25, "currency": "USD" }, "validUntil": "2026-10-22", "status": "expired", "lines": {} }, "action": { "$id": "https://api.sb/routewise.dev/actions/action_1", "operation": "Quote.expire", "status": "done" }, "links": { "self": "https://api.sb/routewise.dev/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const quote = await $.Quote.expire({ quote: 'quote_1' }) ``` **CLI** ```bash npx startup-builder do Quote.expire --json '{"quote":"quote_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Quote.expire({ quote: 'quote_1' })" } } ``` # Quote URL: /business/nouns/quote · Id: `noun:quote` > A Quote is a priced proposal of one or more Offers to one buyer, valid until a date, accepted into an Order. A Quote is a priced proposal of one or more [Offers](/business/nouns/offer) to one buyer, valid until a date. Once accepted, its one-time lines become an [Order](/business/nouns/order) and its recurring lines a [Subscription](/business/nouns/subscription). ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `total` | `money` | Yes | The quoted total. | | `validUntil` | `date` | Yes | The last day it may be accepted. | | `status` | `string` | Yes | One of `draft`, `sent`, `accepted`, `declined`, `expired`, or `superseded`; an expired or superseded Quote never converts. | | `lines` | `json` | Yes | One line per Offer: quantity, list Price, discount percent, net amount, term, and start, one line per ramp year. | | `concessions` | `string[]` | No | Concessions granted, each from the Startup’s fixed concession list, such as a 60-day termination for convenience. | | `paymentTerms` | `json` | No | The `collection`, `terms` and `purchaseOrder` every Invoice from the accepted Quote carries. | ## Object ```json { "$id": "https://api.sb/quietcopy.com/quotes/quote_1", "$type": "Quote", "total": { "amount": 39, "currency": "USD" }, "validUntil": "2026-10-22", "status": "draft", "lines": {}, "concessions": [ "60-day termination for convenience" ], "paymentTerms": {} } ``` ## Relationships - A Quote **is accepted as** one [Order](/business/nouns/order): the [Order](/business/nouns/order) the Quote becomes when the buyer accepts it before it expires. `acceptedAs`, inverse [`quote`](/business/nouns/order#rel-quote). - A Quote **is issued in** one [Deal](/business/nouns/deal): a [Deal](/business/nouns/deal) sends Quotes, each a priced proposal valid until a date. `issuedIn`, inverse [`issues`](/business/nouns/deal#rel-issues). - A Quote **proposes** many [Offers](/business/nouns/offer): a Quote prices one or more [Offers](/business/nouns/offer) for one buyer. `proposes`, inverse [`quotedIn`](/business/nouns/offer#rel-quoted-in). - A Quote **starts subscription** one [Subscription](/business/nouns/subscription): the [Subscription](/business/nouns/subscription) for a Quote’s recurring lines, started when the [Customer](/business/nouns/customer) accepts it. `startsSubscription`, inverse [`quote`](/business/nouns/subscription#rel-quote). ## Lifecycle | State | Meaning | Moves to | | --- | --- | --- | | `draft` (first) | Its lines and terms can still change, and the buyer has not seen it. | `sent` by [Quote.send](/business/nouns/quote/send) | | `sent` | Presented to the buyer with its lines, total and payment terms frozen. | `accepted` by [Quote.accept](/business/nouns/quote/accept); `declined` by [Quote.decline](/business/nouns/quote/decline); `expired` by [Quote.expire](/business/nouns/quote/expire); `superseded` by [Quote.supersede](/business/nouns/quote/supersede) | | `accepted` | Its one-time lines became an Order and its recurring lines a Subscription. | None: it ends here. | | `declined` | The buyer refused it, with the reason in their words. | None: it ends here. | | `expired` | It reached its `validUntil` date unaccepted and never converts. | None: it ends here. | | `superseded` | A newer Quote on the same Deal replaced it; only the newest can be accepted. | None: it ends here. | ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Quote.accept](/business/nouns/quote/accept) | Accept takes a sent Quote before it expires, turning one-time lines into an Order and recurring lines into a Subscription. | [Sales Engineer](/agents/sales/sales-engineer) | [`Quote.accepted`](/business/events/Quote.accepted) | One-way: `send`, `do` | | [Quote.decline](/business/nouns/quote/decline) | Decline records the buyer’s refusal of a sent Quote, with the reason in their words. | [Sales Engineer](/agents/sales/sales-engineer) | [`Quote.declined`](/business/events/Quote.declined) | Two-way: `try`, `send`, `do` | | [Quote.expire](/business/nouns/quote/expire) | Expire closes a sent Quote that reached its validUntil date unaccepted; it never converts afterward. | [Sales Engineer](/agents/sales/sales-engineer) | [`Quote.expired`](/business/events/Quote.expired) | Two-way: `try`, `send`, `do` | | [Quote.request](/business/nouns/quote/request) | Request asks a Startup for terms on one or more Offers, with the volume, term or scope wanted. | [Contact](/business/nouns/contact) | [`Quote.requested`](/business/events/Quote.requested) | None. | | [Quote.send](/business/nouns/quote/send) | Send presents a drafted Quote to its buyer and freezes its lines, total and payment terms. | [Sales Engineer](/agents/sales/sales-engineer) | [`Quote.sent`](/business/events/Quote.sent) | One-way (customer): `send`, `do` | | [Quote.supersede](/business/nouns/quote/supersede) | Supersede replaces a sent Quote with a newer one on the same Deal; only the newest Quote can be accepted. | [Sales Engineer](/agents/sales/sales-engineer) | [`Quote.superseded`](/business/events/Quote.superseded) | Two-way: `try`, `send`, `do` | | [Quote.create](/business/nouns/quote/create) | Creates a Quote. Inherited from [Noun](/business/nouns/noun). | None. | `Quote.created` | Two-way: `try`, `send`, `do` | | [Quote.get](/business/nouns/quote/get) | Returns one Quote by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Quote.list](/business/nouns/quote/list) | Returns Quotes, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Quote.update](/business/nouns/quote/update) | Changes the given properties of a Quote. Inherited from [Noun](/business/nouns/noun). | None. | `Quote.updated` | Two-way: `try`, `send`, `do` | | [Quote.delete](/business/nouns/quote/delete) | Deletes a Quote; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Quote.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Quote.create` | Yes | Yes | Yes | No | | `Quote.get` | Yes | Yes | Yes | Yes | | `Quote.list` | Yes | Yes | Yes | Yes | | `Quote.update` | Yes | Yes | Yes | No | | `Quote.delete` | Yes | Yes | Yes | No | | `Quote.accept` | Yes | No | No | No | | `Quote.decline` | Yes | Yes | Yes | No | | `Quote.expire` | Yes | Yes | Yes | No | | `Quote.request` | Yes | Yes | Yes | No | | `Quote.send` | Yes | No | No | No | | `Quote.supersede` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Accept the latest quote with a party. ``` **API** ```bash curl -X POST https://api.sb/quietcopy.com/quotes/quote_1/accept \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"party":"party_1"}' ``` ```json { "api": "https://api.sb/quietcopy.com", "order": { "$id": "https://api.sb/quietcopy.com/orders/order_1", "$type": "Order", "total": { "amount": 39, "currency": "USD" }, "status": "placed" }, "subscription": { "$id": "https://api.sb/quietcopy.com/subscriptions/subscription_1", "$type": "Subscription", "status": "active" }, "quote": { "$id": "https://api.sb/quietcopy.com/quotes/quote_1", "$type": "Quote", "total": { "amount": 39, "currency": "USD" }, "validUntil": "2026-10-22", "status": "accepted", "lines": {} }, "action": { "$id": "https://api.sb/quietcopy.com/actions/action_1", "operation": "Quote.accept", "status": "done" }, "links": { "self": "https://api.sb/quietcopy.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { order, subscription, quote } = await $.Quote.accept({ quote: 'quote_1', party: 'party_1' }) ``` **CLI** ```bash npx startup-builder do Quote.accept --json '{"quote":"quote_1","party":"party_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Quote.accept({ quote: 'quote_1', party: 'party_1' })" } } ``` ## Example A Quote offers a county planning firm the $900-a-month permit-records [Offer](/business/nouns/offer) at 10% off for a year, plus a $3,000 backfill. It is valid for 14 days. The firm accepts: the backfill becomes an [Order](/business/nouns/order), and the records Offer becomes a [Subscription](/business/nouns/subscription) that keeps the 10% for the term. # request URL: /business/nouns/quote/request · Id: `verb:Quote.request` · Call: `await $.Quote.request({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Request asks a Startup for terms on one or more Offers, with the volume, term or scope wanted. Request asks a [Startup](/business/nouns/startup) for terms on one or more [Offers](/business/nouns/offer), with the volume, term or scope wanted. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `offers` | list of [Offer](/business/nouns/offer) | Yes | The Offers wanted. | | `deal` | [Deal](/business/nouns/deal) | No | The open Deal the terms are for; without one, a new Deal opens. | | `volume` | `integer` | No | Units wanted, such as seats or calls a month. | | `term` | `string` | No | Contract length wanted, such as 12 months. | | `brief` | `json` | No | A Service buyer’s scope, sizes and due dates, such as 82,000 words in three weeks. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `deal` | [Deal](/business/nouns/deal) | Yes | The Deal, waiting on a Quote. | | `quote` | [Quote](/business/nouns/quote) | Yes | The Quote requested, in `draft`. | ## Effects - Emits [`Quote.requested`](/business/events/Quote.requested). - Refuses an Offer that is not open to the requesting party, such as one behind a Waitlist. - Records `by` and `for` when a buyer’s agent asks for its principal under a Mandate. - Starts Send a quote, which supersedes any open Quote on the Deal. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Quote.request](/business/nouns/quote/request) | | An Offer that is not open to the requesting party, such as one behind a Waitlist | [`refused`](/code/api/errors/refused) | Clear what the check names, then call it again. | [Quote.request](/business/nouns/quote/request) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Request the latest quote with an offer. ``` **API** ```bash curl -X POST https://api.sb/routewise.dev/quotes/request \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"offers":["offer_1"]}' ``` ```json { "api": "https://api.sb/routewise.dev", "deal": { "$id": "https://api.sb/routewise.dev/deals/deal_1", "$type": "Deal", "status": "Open" }, "quote": { "$id": "https://api.sb/routewise.dev/quotes/quote_1", "$type": "Quote", "total": { "amount": 25, "currency": "USD" }, "validUntil": "2026-10-22", "status": "draft", "lines": {} }, "action": { "$id": "https://api.sb/routewise.dev/actions/action_1", "operation": "Quote.request", "status": "done" }, "links": { "self": "https://api.sb/routewise.dev/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { deal, quote } = await $.Quote.request({ offers: ['offer_1'] }) ``` **CLI** ```bash npx startup-builder do Quote.request --json '{"offers":["offer_1"]}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Quote.request({ offers: ['offer_1'] })" } } ``` # send URL: /business/nouns/quote/send · Id: `verb:Quote.send` · Call: `await $.Quote.send({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Send presents a drafted Quote to its buyer and freezes its lines, total and payment terms. Send presents a drafted [Quote](/business/nouns/quote) to its buyer and freezes its lines, total and payment terms. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `quote` | [Quote](/business/nouns/quote) | Yes | The draft Quote. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `quote` | [Quote](/business/nouns/quote) | Yes | The sent Quote. | ## Effects - Emits [`Quote.sent`](/business/events/Quote.sent). - Performed by the [Sales Engineer](/agents/sales/sales-engineer). - One-way (customer): it waits out its delay window, and runs in the `send` and `do` modes. - A change after sending supersedes the Quote; a sent Quote is never edited. - Checks each line’s discount against the discount Limit before sending. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Quote.send](/business/nouns/quote/send) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Medium: one-way, bounded (customer) | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | 1 business hour, in which a watcher can pause, redirect or cancel it; then it runs. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Send the latest quote. ``` **API** ```bash curl -X POST https://api.sb/petpantry.shop/quotes/quote_1/send \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/petpantry.shop", "quote": { "$id": "https://api.sb/petpantry.shop/quotes/quote_1", "$type": "Quote", "total": { "amount": 54, "currency": "USD" }, "validUntil": "2026-10-22", "status": "sent", "lines": {} }, "action": { "$id": "https://api.sb/petpantry.shop/actions/action_1", "operation": "Quote.send", "status": "done" }, "links": { "self": "https://api.sb/petpantry.shop/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const quote = await $.Quote.send({ quote: 'quote_1' }) ``` **CLI** ```bash npx startup-builder do Quote.send --json '{"quote":"quote_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Quote.send({ quote: 'quote_1' })" } } ``` Guides that call it: [Make a custom plan for one customer](/products/offers/make-a-custom-plan). # supersede URL: /business/nouns/quote/supersede · Id: `verb:Quote.supersede` · Call: `await $.Quote.supersede({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Supersede replaces a sent Quote with a newer one on the same Deal; only the newest Quote can be accepted. Supersede replaces a sent [Quote](/business/nouns/quote) with a newer one on the same [Deal](/business/nouns/deal); only the newest Quote can be accepted. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `quote` | [Quote](/business/nouns/quote) | Yes | The Quote being replaced. | | `by` | [Quote](/business/nouns/quote) | Yes | The newer Quote that replaces it. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `quote` | [Quote](/business/nouns/quote) | Yes | The superseded Quote, kept on record. | ## Effects - Emits [`Quote.superseded`](/business/events/Quote.superseded). - Performed by the [Sales Engineer](/agents/sales/sales-engineer). - Two-way: it runs at once, in the `try`, `send` and `do` modes. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Quote.supersede](/business/nouns/quote/supersede) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Supersede the latest quote. ``` **API** ```bash curl -X POST https://api.sb/kilnbakery.com/quotes/quote_1/supersede \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"by":"quote_1"}' ``` ```json { "api": "https://api.sb/kilnbakery.com", "quote": { "$id": "https://api.sb/kilnbakery.com/quotes/quote_1", "$type": "Quote", "total": { "amount": 9, "currency": "USD" }, "validUntil": "2026-10-22", "status": "superseded", "lines": {} }, "action": { "$id": "https://api.sb/kilnbakery.com/actions/action_1", "operation": "Quote.supersede", "status": "done" }, "links": { "self": "https://api.sb/kilnbakery.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const quote = await $.Quote.supersede({ quote: 'quote_1', by: 'quote_1' }) ``` **CLI** ```bash npx startup-builder do Quote.supersede --json '{"quote":"quote_1","by":"quote_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Quote.supersede({ quote: 'quote_1', by: 'quote_1' })" } } ``` # Readout URL: /business/nouns/readout · Id: `noun:readout` > A Readout is an Experiment’s result per Variant on its Metric, with the sample size, the interval, and how far the number can be trusted. A Readout is an [Experiment](/business/nouns/experiment)’s result per [Variant](/business/nouns/variant) on its [Metric](/business/nouns/metric), with the sample size, the interval, and how far the number can be trusted. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `value` | `number` | Yes | The Metric’s value for the Variant. | | `n` | `integer` | Yes | How many exposed units it counts. | | `interval` | `json` | No | The low and high bounds of the estimate. | | `readability` | `string` | Yes | One of `A`, `B`, `C`, or `inadmissible`: how far the number can be trusted. | | `pooled` | `boolean` | No | True when exposures from sibling Startups or earlier Portfolio results are pooled in. | ## Object ```json { "$id": "https://api.sb/quietcopy.com/readouts/readout_1", "$type": "Readout", "value": 1, "n": 1, "interval": {}, "readability": "A", "pooled": true } ``` ## Relationships - A Readout **reads** one [Experiment](/business/nouns/experiment): the [Experiment](/business/nouns/experiment) the result belongs to; the learn step drafts the next [Variant](/business/nouns/variant) from it. `reads`, inverse [`readouts`](/business/nouns/experiment#rel-readouts). - A Readout **scores** one [Variant](/business/nouns/variant): the [Variant](/business/nouns/variant) the number describes. `scores`, inverse [`scoredBy`](/business/nouns/variant#rel-scored-by). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Readout.create](/business/nouns/readout/create) | Creates a Readout. Inherited from [Noun](/business/nouns/noun). | None. | `Readout.created` | Two-way: `try`, `send`, `do` | | [Readout.get](/business/nouns/readout/get) | Returns one Readout by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Readout.list](/business/nouns/readout/list) | Returns Readouts, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Readout.update](/business/nouns/readout/update) | Changes the given properties of a Readout. Inherited from [Noun](/business/nouns/noun). | None. | `Readout.updated` | Two-way: `try`, `send`, `do` | | [Readout.delete](/business/nouns/readout/delete) | Deletes a Readout; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Readout.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Readout.create` | Yes | Yes | Yes | No | | `Readout.get` | Yes | Yes | Yes | Yes | | `Readout.list` | Yes | Yes | Yes | Yes | | `Readout.update` | Yes | Yes | Yes | No | | `Readout.delete` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Add a readout to TutorLoop. ``` **API** ```bash curl -X POST https://api.sb/tutorloop.com/readouts \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"value":1,"n":1,"readability":"A"}' ``` ```json { "api": "https://api.sb/tutorloop.com", "readout": { "$id": "https://api.sb/tutorloop.com/readouts/readout_1", "$type": "Readout", "value": 1, "n": 1, "readability": "A" }, "action": { "$id": "https://api.sb/tutorloop.com/actions/action_1", "operation": "Readout.create", "status": "done" }, "links": { "self": "https://api.sb/tutorloop.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const readout = await $.Readout.create({ value: 1, n: 1, readability: 'A' }) ``` **CLI** ```bash npx startup-builder do Readout.create --json '{"value":1,"n":1,"readability":"A"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Readout.create({ value: 1, n: 1, readability: 'A' })" } } ``` ## Example A tutoring [Startup](/business/nouns/startup) reads its two-week pricing [Experiment](/business/nouns/experiment): the challenger converts 4.1% against 3.2% for the control, on 1,900 [Exposures](/business/nouns/exposure), at readability `B`. # Recording URL: /business/nouns/recording · Id: `noun:recording` > A Recording is the replay of one Visit or one agent browser session, masked at capture. A Recording is the replay of one [Visit](/business/nouns/visit) or one agent browser session, masked at capture. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `visit` | [Visit](/business/nouns/visit) | No | The Visit it replays, for a person’s session. | | `action` | [Action](/business/nouns/action) | No | The agent Action whose browser session it replays. | | `file` | [File](/business/nouns/file) | No | The rendered video File, when one is rendered. | | `seconds` | `integer` | No | Its length in seconds. | ## Object ```json { "$id": "https://api.sb/routewise.dev/recordings/recording_1", "$type": "Recording", "visit": "visit_1", "action": "action_1", "file": "file_1", "seconds": 1 } ``` ## Relationships - A Recording **replays** one [Visit](/business/nouns/visit): a Recording replays one [Visit](/business/nouns/visit), linked from every funnel step that Visit reached. `replays`, inverse [`recording`](/business/nouns/visit#rel-recording). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Recording.get](/business/nouns/recording/get) | Returns one Recording by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Recording.list](/business/nouns/recording/list) | Returns Recordings, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | A Recording is kept forever and never edited: it has no `update` or `delete`. ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Recording.get` | Yes | Yes | Yes | Yes | | `Recording.list` | Yes | Yes | Yes | Yes | ## Call it **Ask** ```text Show me the latest recording. ``` **API** ```bash curl https://api.sb/ledgerlark.com/recordings/recording_1 \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/ledgerlark.com", "$type": "Recording", "$id": "https://api.sb/ledgerlark.com/recordings/recording_1", "recording": { "$id": "https://api.sb/ledgerlark.com/recordings/recording_1", "$type": "Recording", "visit": "visit_1", "action": "action_1" }, "links": { "self": "https://api.sb/ledgerlark.com/recordings/recording_1", "up": "https://api.sb/ledgerlark.com/recordings" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const recording = await $.Recording.get({ id: 'recording_1' }) ``` **CLI** ```bash npx startup-builder do Recording.get --json '{"id":"recording_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Recording.get({ id: 'recording_1' })" } } ``` ## Example A buyer abandons checkout on a travel-insurance [Site](/business/nouns/site). Her Recording replays the 94-second [Visit](/business/nouns/visit) with card fields masked, and it shows her stuck on the date picker. # drill URL: /business/nouns/recovery-objective/drill · Id: `verb:RecoveryObjective.drill` · Call: `await $.RecoveryObjective.drill({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Drill restores one Capability’s records into an isolated namespace and records whether the restore met both objectives. Drill restores one [Capability](/business/nouns/capability)’s records into an isolated namespace and records whether the restore met both objectives. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `objective` | [Recovery Objective](/business/nouns/recovery-objective) | Yes | The Recovery Objective to prove. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `objective` | [Recovery Objective](/business/nouns/recovery-objective) | Yes | The objective with its last drill result. | ## Effects - Emits [`RecoveryObjective.drilled`](/business/events/RecoveryObjective.drilled). - Performed by the [Reliability Engineer](/agents/engineering/reliability-engineer). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Opens an Incident when a restore misses its recovery point or recovery time. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [RecoveryObjective.drill](/business/nouns/recovery-objective/drill) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Drill the latest recovery objective. ``` **API** ```bash curl -X POST https://api.sb/shiftnote.app/recovery-objectives/recovery_objective_1/drill \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/shiftnote.app", "objective": { "$id": "https://api.sb/shiftnote.app/recovery-objectives/recovery_objective_1", "$type": "RecoveryObjective", "recoveryPoint": "Example recovery point", "recoveryTime": "Example recovery time", "drillEvery": "Example drill every" }, "action": { "$id": "https://api.sb/shiftnote.app/actions/action_1", "operation": "RecoveryObjective.drill", "status": "done" }, "links": { "self": "https://api.sb/shiftnote.app/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const objective = await $.RecoveryObjective.drill({ objective: 'recovery_objective_1' }) ``` **CLI** ```bash npx startup-builder do RecoveryObjective.drill --json '{"objective":"recovery_objective_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.RecoveryObjective.drill({ objective: 'recovery_objective_1' })" } } ``` # Recovery Objective URL: /business/nouns/recovery-objective · Id: `noun:recovery-objective` > A Recovery Objective sets how much data one Capability may lose and how fast it returns, proven by a restore drill on a cadence. A Recovery Objective sets how much data one [Capability](/business/nouns/capability) may lose and how fast it returns, proven by a restore drill on a cadence. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `recoveryPoint` | `string` | Yes | The most data a failure may lose, as a window such as `15m`. | | `recoveryTime` | `string` | Yes | How fast the Capability returns after a failure, as a window such as `4h`. | | `drillEvery` | `string` | Yes | The restore drill cadence, such as `quarterly`. | | `lastDrill` | `datetime` | No | When the last restore drill met both objectives. | ## Object ```json { "$id": "https://api.sb/routewise.dev/recovery-objectives/recovery_objective_1", "$type": "RecoveryObjective", "recoveryPoint": "Example recovery point", "recoveryTime": "Example recovery time", "drillEvery": "Example drill every", "lastDrill": "2026-10-22T12:00:00Z" } ``` ## Relationships - A Recovery Objective **has** one [Capability](/business/nouns/capability): the [Capability](/business/nouns/capability) the objective restores. `capability`, inverse [`recoveryObjectives`](/business/nouns/capability#rel-recovery-objectives). - A Recovery Objective **has** one [Startup](/business/nouns/startup): one Recovery Objective for each [Capability](/business/nouns/capability) the [Startup](/business/nouns/startup) depends on. `startup`, inverse [`recoveryObjectives`](/business/nouns/startup#rel-recovery-objectives). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [RecoveryObjective.drill](/business/nouns/recovery-objective/drill) | Drill restores one Capability’s records into an isolated namespace and records whether the restore met both objectives. | [Reliability Engineer](/agents/engineering/reliability-engineer) | [`RecoveryObjective.drilled`](/business/events/RecoveryObjective.drilled) | Two-way: `try`, `send`, `do` | | [RecoveryObjective.create](/business/nouns/recovery-objective/create) | Creates a Recovery Objective. Inherited from [Noun](/business/nouns/noun). | None. | `RecoveryObjective.created` | Two-way: `try`, `send`, `do` | | [RecoveryObjective.get](/business/nouns/recovery-objective/get) | Returns one Recovery Objective by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [RecoveryObjective.list](/business/nouns/recovery-objective/list) | Returns Recovery Objectives, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [RecoveryObjective.update](/business/nouns/recovery-objective/update) | Changes the given properties of a Recovery Objective. Inherited from [Noun](/business/nouns/noun). | None. | `RecoveryObjective.updated` | Two-way: `try`, `send`, `do` | | [RecoveryObjective.delete](/business/nouns/recovery-objective/delete) | Deletes a Recovery Objective; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `RecoveryObjective.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `RecoveryObjective.create` | Yes | Yes | Yes | No | | `RecoveryObjective.get` | Yes | Yes | Yes | Yes | | `RecoveryObjective.list` | Yes | Yes | Yes | Yes | | `RecoveryObjective.update` | Yes | Yes | Yes | No | | `RecoveryObjective.delete` | Yes | Yes | Yes | No | | `RecoveryObjective.drill` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Drill the latest recovery objective. ``` **API** ```bash curl -X POST https://api.sb/shiftnote.app/recovery-objectives/recovery_objective_1/drill \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/shiftnote.app", "objective": { "$id": "https://api.sb/shiftnote.app/recovery-objectives/recovery_objective_1", "$type": "RecoveryObjective", "recoveryPoint": "Example recovery point", "recoveryTime": "Example recovery time", "drillEvery": "Example drill every" }, "action": { "$id": "https://api.sb/shiftnote.app/actions/action_1", "operation": "RecoveryObjective.drill", "status": "done" }, "links": { "self": "https://api.sb/shiftnote.app/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const objective = await $.RecoveryObjective.drill({ objective: 'recovery_objective_1' }) ``` **CLI** ```bash npx startup-builder do RecoveryObjective.drill --json '{"objective":"recovery_objective_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.RecoveryObjective.drill({ objective: 'recovery_objective_1' })" } } ``` ## Example Payments carries a Recovery Objective of `15m` for data and `1h` for service, drilled quarterly. The last drill restored the namespace in 22 minutes, so both objectives held. # Referral URL: /business/nouns/referral · Id: `noun:referral` > A Referral is a Contact, Customer, or Partner sending a Lead to a Startup, with any reward it earns. A Referral is a [Contact](/business/nouns/contact), [Customer](/business/nouns/customer), or [Partner](/business/nouns/partner) sending a [Lead](/business/nouns/lead) to a [Startup](/business/nouns/startup), with any reward it earns. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `reward` | `money` | No | What the referrer earns. | | `rewardKind` | `string` | No | What the referrer earns: earlier `access`, or `cash`, which pays only after Live. | ## Object ```json { "$id": "https://api.sb/patentpad.com/referrals/referral_1", "$type": "Referral", "reward": { "amount": 499, "currency": "USD" }, "rewardKind": "access" } ``` ## Relationships - A Referral **earns** one [Commission](/business/nouns/commission): the [Commission](/business/nouns/commission) a [Partner](/business/nouns/partner)’s Referral earns on the revenue it brings, self-serve or through a [Deal](/business/nouns/deal). `earns`, inverse [`referral`](/business/nouns/commission#rel-referral). - A Referral **is made by** one [Party](/business/nouns/party): the [Party](/business/nouns/party) who sends a Referral earns its reward. `madeBy`, inverse [`referrals`](/business/nouns/party#rel-referrals). - A Referral **refers** one [Lead](/business/nouns/lead): each Referral sends one [Lead](/business/nouns/lead) to the [Startup](/business/nouns/startup). `refers`, inverse [`referredBy`](/business/nouns/lead#rel-referred-by). - A Referral **sources** many [Deals](/business/nouns/deal): the [Deals](/business/nouns/deal) a Referral opened; when one is won, its revenue earns the [Partner](/business/nouns/partner)’s [Commission](/business/nouns/commission). `sources`, inverse [`sourcedBy`](/business/nouns/deal#rel-sourced-by). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Referral.create](/business/nouns/referral/create) | Creates a Referral. Inherited from [Noun](/business/nouns/noun). | None. | `Referral.created` | Two-way: `try`, `send`, `do` | | [Referral.get](/business/nouns/referral/get) | Returns one Referral by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Referral.list](/business/nouns/referral/list) | Returns Referrals, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Referral.update](/business/nouns/referral/update) | Changes the given properties of a Referral. Inherited from [Noun](/business/nouns/noun). | None. | `Referral.updated` | Two-way: `try`, `send`, `do` | | [Referral.delete](/business/nouns/referral/delete) | Deletes a Referral; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Referral.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Referral.create` | Yes | Yes | Yes | No | | `Referral.get` | Yes | Yes | Yes | Yes | | `Referral.list` | Yes | Yes | Yes | Yes | | `Referral.update` | Yes | Yes | Yes | No | | `Referral.delete` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Add a referral to ShiftNote. ``` **API** ```bash curl -X POST https://api.sb/shiftnote.app/referrals \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"reward":{"amount":79,"currency":"USD"}}' ``` ```json { "api": "https://api.sb/shiftnote.app", "referral": { "$id": "https://api.sb/shiftnote.app/referrals/referral_1", "$type": "Referral", "reward": { "amount": 79, "currency": "USD" }, "rewardKind": "access" }, "action": { "$id": "https://api.sb/shiftnote.app/actions/action_1", "operation": "Referral.create", "status": "done" }, "links": { "self": "https://api.sb/shiftnote.app/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const referral = await $.Referral.create({ reward: { amount: 79, currency: 'USD' } }) ``` **CLI** ```bash npx startup-builder do Referral.create --json '{"reward":{"amount":79,"currency":"USD"}}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Referral.create({ reward: { amount: 79, currency: 'USD' } })" } } ``` ## Example A music teacher sends her link to a colleague, who signs up for the lesson-booking [App](/business/nouns/app). The Referral credits the teacher one free month when the colleague pays. # admit URL: /business/nouns/registration/admit · Id: `verb:Registration.admit` · Call: `await $.Registration.admit({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Admit gives the next Contact in line a place at a Gathering when one frees up or its capacity rises. Admit gives the next waitlisted person a place at a [Gathering](/business/nouns/gathering) when one frees up or its capacity rises. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `registration` | [Registration](/business/nouns/registration) | Yes | The waitlisted Registration. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `registration` | [Registration](/business/nouns/registration) | Yes | The Registration, now `registered`. | ## Effects - Emits [`Registration.admitted`](/business/events/Registration.admitted). - Performed by the [Marketing Lead](/agents/marketing/marketing-lead). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Refuses while the Gathering is at capacity. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Registration.admit](/business/nouns/registration/admit) | | The Gathering is at capacity | [`refused`](/code/api/errors/refused) | Clear what the check names, then call it again. | [Registration.admit](/business/nouns/registration/admit) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Admit the latest registration. ``` **API** ```bash curl -X POST https://api.sb/tutorloop.com/registrations/registration_1/admit \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/tutorloop.com", "registration": { "$id": "https://api.sb/tutorloop.com/registrations/registration_1", "$type": "Registration", "status": "invited" }, "action": { "$id": "https://api.sb/tutorloop.com/actions/action_1", "operation": "Registration.admit", "status": "done" }, "links": { "self": "https://api.sb/tutorloop.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const registration = await $.Registration.admit({ registration: 'registration_1' }) ``` **CLI** ```bash npx startup-builder do Registration.admit --json '{"registration":"registration_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Registration.admit({ registration: 'registration_1' })" } } ``` # approve URL: /business/nouns/registration/approve · Id: `verb:Registration.approve` · Call: `await $.Registration.approve({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Approve gives a requested place at a Gathering to the Contact who asked, or a place in line when the Gathering is full. Approve gives a requested place at a [Gathering](/business/nouns/gathering) to the person who asked, or a waitlist place when the Gathering is full. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `registration` | [Registration](/business/nouns/registration) | Yes | The requested Registration. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `registration` | [Registration](/business/nouns/registration) | Yes | The Registration, `registered` or `waitlisted`. | ## Effects - Emits [`Registration.approved`](/business/events/Registration.approved). - Performed by the [Marketing Lead](/agents/marketing/marketing-lead). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Sends the confirmation and the join link once the place is held. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Registration.approve](/business/nouns/registration/approve) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Approve the latest registration. ``` **API** ```bash curl -X POST https://api.sb/tutorloop.com/registrations/registration_1/approve \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/tutorloop.com", "registration": { "$id": "https://api.sb/tutorloop.com/registrations/registration_1", "$type": "Registration", "status": "invited" }, "action": { "$id": "https://api.sb/tutorloop.com/actions/action_1", "operation": "Registration.approve", "status": "done" }, "links": { "self": "https://api.sb/tutorloop.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const registration = await $.Registration.approve({ registration: 'registration_1' }) ``` **CLI** ```bash npx startup-builder do Registration.approve --json '{"registration":"registration_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Registration.approve({ registration: 'registration_1' })" } } ``` # attend URL: /business/nouns/registration/attend · Id: `verb:Registration.attend` · Call: `await $.Registration.attend({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Attend records that a registered Contact joined the Gathering; an online room calls it on join. Attend records that a registered person joined the [Gathering](/business/nouns/gathering); an online room calls it when the person joins. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `registration` | [Registration](/business/nouns/registration) | Yes | The Registration of the Contact who joined. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `registration` | [Registration](/business/nouns/registration) | Yes | The Registration, now `attended`. | ## Effects - Emits [`Registration.attended`](/business/events/Registration.attended). - Performed by the [Marketing Lead](/agents/marketing/marketing-lead). - Two-way: it runs at once, in the `try`, `send` and `do` modes. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Registration.attend](/business/nouns/registration/attend) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Attend the latest registration. ``` **API** ```bash curl -X POST https://api.sb/shiftnote.app/registrations/registration_1/attend \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/shiftnote.app", "registration": { "$id": "https://api.sb/shiftnote.app/registrations/registration_1", "$type": "Registration", "status": "attended" }, "action": { "$id": "https://api.sb/shiftnote.app/actions/action_1", "operation": "Registration.attend", "status": "done" }, "links": { "self": "https://api.sb/shiftnote.app/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const registration = await $.Registration.attend({ registration: 'registration_1' }) ``` **CLI** ```bash npx startup-builder do Registration.attend --json '{"registration":"registration_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Registration.attend({ registration: 'registration_1' })" } } ``` # Registration URL: /business/nouns/registration · Id: `noun:registration` > A Registration is one person’s place at a Gathering: invited, requested, or waitlisted, then registered, then attended or no-show. A Registration is one person’s place at a [Gathering](/business/nouns/gathering): invited, requested, or waitlisted, then registered, then attended or no-show. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `status` | `string` | Yes | One of `invited`, `requested`, `waitlisted`, `registered`, `attended`, or `noShow`. | | `registeredAt` | `datetime` | No | When the place was confirmed. | ## Object ```json { "$id": "https://api.sb/patentpad.com/registrations/registration_1", "$type": "Registration", "status": "invited", "registeredAt": "2026-10-22T12:00:00Z" } ``` ## Relationships - A Registration **has** one [Gathering](/business/nouns/gathering): a [Gathering](/business/nouns/gathering) admits Registrations up to its capacity, then waitlists the rest. `gathering`, inverse [`admits`](/business/nouns/gathering#rel-admits). - A Registration **names** one [Contact](/business/nouns/contact): each Registration holds one [Contact](/business/nouns/contact)’s place; one Contact registers for many [Gatherings](/business/nouns/gathering). `names`, inverse [`registrations`](/business/nouns/contact#rel-registrations). ## Lifecycle | State | Meaning | Moves to | | --- | --- | --- | | `invited` (first) | Offered a place, by the host’s invitation or the Gathering’s public Page, and not yet taken. | `registered` by [Gathering.register](/business/nouns/gathering/register); `waitlisted` by [Gathering.register](/business/nouns/gathering/register); `requested` by [Gathering.register](/business/nouns/gathering/register) | | `requested` | Asked for a place at a Gathering whose host approves each one. | `registered` by [Registration.approve](/business/nouns/registration/approve); `waitlisted` by [Registration.approve](/business/nouns/registration/approve) | | `waitlisted` | Next in line for a place, in the order they asked. | `registered` by [Registration.admit](/business/nouns/registration/admit) | | `registered` | Holds a place; the reminders and the join link go to the Contact. | `attended` by [Registration.attend](/business/nouns/registration/attend); `noShow` on [`Registration.missed`](/business/nouns/registration#registrationmissed) | | `attended` | Joined the Gathering. | None: it ends here. | | `noShow` | Held a place and never joined before the Gathering ended. | None: it ends here. | ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Registration.admit](/business/nouns/registration/admit) | Admit gives the next Contact in line a place at a Gathering when one frees up or its capacity rises. | [Marketing Lead](/agents/marketing/marketing-lead) | [`Registration.admitted`](/business/events/Registration.admitted) | Two-way: `try`, `send`, `do` | | [Registration.approve](/business/nouns/registration/approve) | Approve gives a requested place at a Gathering to the Contact who asked, or a place in line when the Gathering is full. | [Marketing Lead](/agents/marketing/marketing-lead) | [`Registration.approved`](/business/events/Registration.approved) | Two-way: `try`, `send`, `do` | | [Registration.attend](/business/nouns/registration/attend) | Attend records that a registered Contact joined the Gathering; an online room calls it on join. | [Marketing Lead](/agents/marketing/marketing-lead) | [`Registration.attended`](/business/events/Registration.attended) | Two-way: `try`, `send`, `do` | | [Registration.create](/business/nouns/registration/create) | Creates a Registration. Inherited from [Noun](/business/nouns/noun). | None. | `Registration.created` | Two-way: `try`, `send`, `do` | | [Registration.get](/business/nouns/registration/get) | Returns one Registration by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Registration.list](/business/nouns/registration/list) | Returns Registrations, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Registration.update](/business/nouns/registration/update) | Changes the given properties of a Registration. Inherited from [Noun](/business/nouns/noun). | None. | `Registration.updated` | Two-way: `try`, `send`, `do` | | [Registration.delete](/business/nouns/registration/delete) | Deletes a Registration; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Registration.deleted` | One-way: `send`, `do` | ## Events Events no Verb emits. Each Verb’s Event is in the Verbs table above; every Event is delivered in the same shape. ### Registration.missed A Gathering ended, and a Contact who held a place never joined. Raised by a clock. | Field | Type | Required | Description | | --- | --- | --- | --- | | `name` | `string` | Yes | `Registration.missed`. | | `at` | `datetime` | Yes | When it happened. | | `seq` | `integer` | No | Its position in the namespace, one more than the Event before; any seq is a cursor into the history. | | `data` | `json` | Yes | The Thing as the Action left it. | | `data.registration` | [Registration](/business/nouns/registration) | Yes | The Registration as the change left it. | | `data.registration.status` | `string` | Yes | One of `invited`, `requested`, `waitlisted`, `registered`, `attended`, or `noShow`. | | `data.registration.registeredAt` | `datetime` | No | When the place was confirmed. | | `data.previous.status` | `string` | Yes | The `status` before this Event: `registered`. | ```json { "$id": "https://api.sb/patentpad.com/events/event_1", "$type": "Event", "name": "Registration.missed", "at": "2026-10-22T12:00:00Z", "data": { "registration": { "$id": "https://api.sb/patentpad.com/registrations/registration_1", "$type": "Registration", "status": "noShow", "registeredAt": "2026-10-22T12:00:00Z" }, "previous": { "status": "registered" } }, "seq": 1 } ``` ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Registration.create` | Yes | Yes | Yes | No | | `Registration.get` | Yes | Yes | Yes | Yes | | `Registration.list` | Yes | Yes | Yes | Yes | | `Registration.update` | Yes | Yes | Yes | No | | `Registration.delete` | Yes | Yes | Yes | No | | `Registration.admit` | Yes | Yes | Yes | No | | `Registration.approve` | Yes | Yes | Yes | No | | `Registration.attend` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Approve the latest registration. ``` **API** ```bash curl -X POST https://api.sb/tutorloop.com/registrations/registration_1/approve \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/tutorloop.com", "registration": { "$id": "https://api.sb/tutorloop.com/registrations/registration_1", "$type": "Registration", "status": "invited" }, "action": { "$id": "https://api.sb/tutorloop.com/actions/action_1", "operation": "Registration.approve", "status": "done" }, "links": { "self": "https://api.sb/tutorloop.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const registration = await $.Registration.approve({ registration: 'registration_1' }) ``` **CLI** ```bash npx startup-builder do Registration.approve --json '{"registration":"registration_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Registration.approve({ registration: 'registration_1' })" } } ``` ## Example A product manager registers for a pricing workshop and gets a calendar invite. She joins 10 minutes late, and her Registration moves from `registered` to `attended`. # Relationship URL: /business/nouns/relationship · Id: `noun:relationship` > A Relationship is a standing Action between two Things, read in the present tense and typed by a Verb whose forms give its reverse. A Relationship is a standing link between two [Things](/business/nouns/thing), typed by a [Verb](/business/nouns/verb), declared once and read from both ends. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `predicate` | `string` | Yes | The name read from the source, such as `makes`. | | `inverse` | `string` | Yes | The name read from the target, such as `madeBy`. | | `provenance` | `string` | No | Who asserted it: `Stated`, `Ratified`, `Inferred`, or `Observed`. | ## Object ```json { "$id": "https://api.sb/tutorloop.com/relationships/relationship_1", "$type": "Relationship", "predicate": "Example predicate", "inverse": "Example inverse", "provenance": "Stated" } ``` ## Relationships - A Relationship **is typed by** one [Verb](/business/nouns/verb): a Relationship reads through a [Verb](/business/nouns/verb) whose forms name it from each side, such as `makes` and `madeBy`. `typedBy`, inverse [`types`](/business/nouns/verb#rel-types). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Relationship.create](/business/nouns/relationship/create) | Creates a Relationship. Inherited from [Noun](/business/nouns/noun). | None. | `Relationship.created` | Two-way: `try`, `send`, `do` | | [Relationship.get](/business/nouns/relationship/get) | Returns one Relationship by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Relationship.list](/business/nouns/relationship/list) | Returns Relationships, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Relationship.update](/business/nouns/relationship/update) | Changes the given properties of a Relationship. Inherited from [Noun](/business/nouns/noun). | None. | `Relationship.updated` | Two-way: `try`, `send`, `do` | | [Relationship.delete](/business/nouns/relationship/delete) | Deletes a Relationship; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Relationship.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Relationship.create` | Yes | Yes | Yes | No | | `Relationship.get` | Yes | Yes | Yes | Yes | | `Relationship.list` | Yes | Yes | Yes | Yes | | `Relationship.update` | Yes | Yes | Yes | No | | `Relationship.delete` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Add a relationship to QuietCopy. ``` **API** ```bash curl -X POST https://api.sb/quietcopy.com/relationships \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"predicate":"Example predicate","inverse":"Example inverse"}' ``` ```json { "api": "https://api.sb/quietcopy.com", "relationship": { "$id": "https://api.sb/quietcopy.com/relationships/relationship_1", "$type": "Relationship", "predicate": "Example predicate", "inverse": "Example inverse" }, "action": { "$id": "https://api.sb/quietcopy.com/actions/action_1", "operation": "Relationship.create", "status": "done" }, "links": { "self": "https://api.sb/quietcopy.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const relationship = await $.Relationship.create({ predicate: 'Example predicate', inverse: 'Example inverse' }) ``` **CLI** ```bash npx startup-builder do Relationship.create --json '{"predicate":"Example predicate","inverse":"Example inverse"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Relationship.create({ predicate: 'Example predicate', inverse: 'Example inverse' })" } } ``` ## Example `Customer accepts Offer` is one Relationship, declared once. The [Customer](/business/nouns/customer) page shows `accepts`, and the [Offer](/business/nouns/offer) page shows `acceptedBy`. # Renewal URL: /business/nouns/renewal · Id: `noun:renewal` > A Renewal is the Deal for a term Subscription’s next term, opened before the term ends and closed renewed, expanded, contracted, or churned. A Renewal is the [Deal](/business/nouns/deal) for a term [Subscription](/business/nouns/subscription)’s next term, opened before the term ends and closed renewed, expanded, contracted, or churned. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `termEndsAt` | `datetime` | Yes | When the current term ends, read from the Subscription. | | `openedAt` | `datetime` | Yes | When it opened: by default 90 days before the term ends. | | `usageReview` | `text` | No | Usage against each Entitlement over the term, written before any Quote. | | `noticeSentAt` | `datetime` | No | When the renewal notice the legal floor requires went out, with the date, Price and cancel link. | | `saveOffer` | `text` | No | The one save offer shown on cancel; it never blocks the cancel. | | `outcome` | `string` | No | One of `renewed`, `expanded`, `contracted`, or `churned`, computed from the Subscription’s Events at the term end. |
Inherited from [Deal](/business/nouns/deal): 6 properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `status` | `string` | Yes | One of `Open`, `Qualified`, `Proposed`, `Won`, or `Lost`. | | `value` | `money` | No | What the Deal is worth if won. | | `owner` | [Worker](/business/nouns/worker) | No | The Worker who runs it. | | `closesOn` | `date` | No | The date the buyer expects to decide. | | `statusSince` | `datetime` | No | When it entered its current status, computed from its Events. | | `nextStep` | `text` | No | The next dated step agreed with the buyer. |
## Object ```json { "$id": "https://api.sb/tutorloop.com/renewals/renewal_1", "$type": "Renewal", "status": "Open", "value": { "amount": 60, "currency": "USD" }, "owner": "worker_1", "closesOn": "2026-10-22", "statusSince": "2026-10-22T12:00:00Z", "nextStep": "Example next step", "termEndsAt": "2026-10-22T12:00:00Z", "openedAt": "2026-10-22T12:00:00Z", "usageReview": "Example usage review", "noticeSentAt": "2026-10-22T12:00:00Z", "saveOffer": "Example save offer", "outcome": "renewed" } ``` ## Relationships - A Renewal **renews** one [Subscription](/business/nouns/subscription): each Renewal decides one term of one [Subscription](/business/nouns/subscription); a Subscription has one Renewal per term. `renews`, inverse [`renewals`](/business/nouns/subscription#rel-renewals). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Renewal.open](/business/nouns/renewal/open) | Open starts the Renewal for a term Subscription before its term ends, with a usage review and any notice the legal floor requires. | [Success Manager](/agents/customer/success-manager) | [`Renewal.opened`](/business/events/Renewal.opened) | Two-way: `try`, `send`, `do` | | [Renewal.create](/business/nouns/renewal/create) | Creates a Renewal. Inherited from [Noun](/business/nouns/noun). | None. | `Renewal.created` | Two-way: `try`, `send`, `do` | | [Renewal.get](/business/nouns/renewal/get) | Returns one Renewal by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Renewal.list](/business/nouns/renewal/list) | Returns Renewals, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Renewal.update](/business/nouns/renewal/update) | Changes the given properties of a Renewal. Inherited from [Noun](/business/nouns/noun). | None. | `Renewal.updated` | Two-way: `try`, `send`, `do` | | [Renewal.delete](/business/nouns/renewal/delete) | Deletes a Renewal; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Renewal.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Renewal.create` | Yes | Yes | Yes | No | | `Renewal.get` | Yes | Yes | Yes | Yes | | `Renewal.list` | Yes | Yes | Yes | Yes | | `Renewal.update` | Yes | Yes | Yes | No | | `Renewal.delete` | Yes | Yes | Yes | No | | `Renewal.open` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Open the latest renewal with a subscription. ``` **API** ```bash curl -X POST https://api.sb/tutorloop.com/renewals/open \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"subscription":"subscription_1"}' ``` ```json { "api": "https://api.sb/tutorloop.com", "renewal": { "$id": "https://api.sb/tutorloop.com/renewals/renewal_1", "$type": "Renewal", "status": "Open", "termEndsAt": "2026-10-22T12:00:00Z", "openedAt": "2026-10-22T12:00:00Z" }, "action": { "$id": "https://api.sb/tutorloop.com/actions/action_1", "operation": "Renewal.open", "status": "done" }, "links": { "self": "https://api.sb/tutorloop.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const renewal = await $.Renewal.open({ subscription: 'subscription_1' }) ``` **CLI** ```bash npx startup-builder do Renewal.open --json '{"subscription":"subscription_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Renewal.open({ subscription: 'subscription_1' })" } } ``` ## Example A 12-seat litigation team's Renewal opens 90 days before its term ends, and the usage review shows 9 seats active. The [Success Manager](/agents/customer/success-manager) sends a 10-seat [Quote](/business/nouns/quote), the team accepts it, and the Renewal closes `contracted`. # open URL: /business/nouns/renewal/open · Id: `verb:Renewal.open` · Call: `await $.Renewal.open({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Open starts the Renewal for a term Subscription before its term ends, with a usage review and any notice the legal floor requires. Open starts the [Renewal](/business/nouns/renewal) for a term [Subscription](/business/nouns/subscription) before its term ends, with a usage review and any notice the legal floor requires. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `subscription` | [Subscription](/business/nouns/subscription) | Yes | The Subscription whose term is ending. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `renewal` | [Renewal](/business/nouns/renewal) | Yes | The open Renewal. | ## Effects - Emits [`Renewal.opened`](/business/events/Renewal.opened). - Performed by the [Success Manager](/agents/customer/success-manager). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Runs 90 days before the term ends with no caller; a Setting at any namespace changes the lead time. - Drafts an expansion or right-size Quote when usage moved during the term. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Renewal.open](/business/nouns/renewal/open) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Open the latest renewal with a subscription. ``` **API** ```bash curl -X POST https://api.sb/tutorloop.com/renewals/open \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"subscription":"subscription_1"}' ``` ```json { "api": "https://api.sb/tutorloop.com", "renewal": { "$id": "https://api.sb/tutorloop.com/renewals/renewal_1", "$type": "Renewal", "status": "Open", "termEndsAt": "2026-10-22T12:00:00Z", "openedAt": "2026-10-22T12:00:00Z" }, "action": { "$id": "https://api.sb/tutorloop.com/actions/action_1", "operation": "Renewal.open", "status": "done" }, "links": { "self": "https://api.sb/tutorloop.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const renewal = await $.Renewal.open({ subscription: 'subscription_1' }) ``` **CLI** ```bash npx startup-builder do Renewal.open --json '{"subscription":"subscription_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Renewal.open({ subscription: 'subscription_1' })" } } ``` # Reserved Act URL: /business/nouns/reserved-act · Id: `noun:reserved-act` > A Reserved Act is a Verb the law reserves to the holder of a named Credential, so its Function is always human. A Reserved Act is a [Verb](/business/nouns/verb) the law reserves to the holder of a named [Credential](/business/nouns/credential), so its [Function](/business/nouns/function) is always human. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `jurisdiction` | `string` | Yes | Where the law reserves it. | ## Object ```json { "$id": "https://api.sb/routewise.dev/reserved-acts/reserved_act_1", "$type": "ReservedAct", "jurisdiction": "US-DE" } ``` ## Relationships - A Reserved Act **has** many [Attestations](/business/nouns/attestation): the Reserved Act the [Attestation](/business/nouns/attestation) records as performed or declined. `attestations`, inverse [`performs`](/business/nouns/attestation#rel-performs). - A Reserved Act **requires** many [Credentials](/business/nouns/credential): a [Credential](/business/nouns/credential) lets its holder perform the Reserved Acts the law keeps for it, in its jurisdiction. `requires`, inverse [`authorizes`](/business/nouns/credential#rel-authorizes). - A Reserved Act **reserves** one [Verb](/business/nouns/verb): the [Verb](/business/nouns/verb) the law reserves to a credentialed [Human](/business/nouns/human) in the act’s jurisdiction. `reserves`, inverse [`reservedBy`](/business/nouns/verb#rel-reserved-by). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [ReservedAct.create](/business/nouns/reserved-act/create) | Creates a Reserved Act. Inherited from [Noun](/business/nouns/noun). | None. | `ReservedAct.created` | Two-way: `try`, `send`, `do` | | [ReservedAct.get](/business/nouns/reserved-act/get) | Returns one Reserved Act by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [ReservedAct.list](/business/nouns/reserved-act/list) | Returns Reserved Acts, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [ReservedAct.update](/business/nouns/reserved-act/update) | Changes the given properties of a Reserved Act. Inherited from [Noun](/business/nouns/noun). | None. | `ReservedAct.updated` | Two-way: `try`, `send`, `do` | | [ReservedAct.delete](/business/nouns/reserved-act/delete) | Deletes a Reserved Act; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `ReservedAct.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `ReservedAct.create` | Yes | Yes | Yes | No | | `ReservedAct.get` | Yes | Yes | Yes | Yes | | `ReservedAct.list` | Yes | Yes | Yes | Yes | | `ReservedAct.update` | Yes | Yes | Yes | No | | `ReservedAct.delete` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Add a reserved act to QuietCopy. ``` **API** ```bash curl -X POST https://api.sb/quietcopy.com/reserved-acts \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"jurisdiction":"US-DE"}' ``` ```json { "api": "https://api.sb/quietcopy.com", "reservedAct": { "$id": "https://api.sb/quietcopy.com/reserved-acts/reserved_act_1", "$type": "ReservedAct", "jurisdiction": "US-DE" }, "action": { "$id": "https://api.sb/quietcopy.com/actions/action_1", "operation": "ReservedAct.create", "status": "done" }, "links": { "self": "https://api.sb/quietcopy.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const reservedAct = await $.ReservedAct.create({ jurisdiction: 'US-DE' }) ``` **CLI** ```bash npx startup-builder do ReservedAct.create --json '{"jurisdiction":"US-DE"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.ReservedAct.create({ jurisdiction: 'US-DE' })" } } ``` ## Example Signing an appraisal report is a Reserved Act. Only a [Human](/business/nouns/human) with an appraiser Credential performs it. # Review URL: /business/nouns/review · Id: `noun:review` > A Review is one person’s rated evaluation of a Product, Offer or Brand, shown on a Site or an outside venue and mirrored from there. A Review is one person’s rated evaluation of a [Product](/business/nouns/product), [Offer](/business/nouns/offer) or [Brand](/business/nouns/brand), shown on a [Site](/business/nouns/site) or an outside venue and mirrored from there. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `rating` | `integer` | Yes | The score, from 1 to 5. | | `body` | `text` | No | The reviewer’s words. | | `venue` | `string` | No | The venue it was posted on, by id; empty for the Startup’s own Site. | | `displayConsent` | `boolean` | No | True once the reviewer agreed it may be shown on the Startup’s own Pages. Never randomized. | | `status` | `string` | Yes | Where it stands; a removed Review is kept, never deleted. | | `customer` | [Customer](/business/nouns/customer) | No | The Customer who wrote it, when known. | ## Object ```json { "$id": "https://api.sb/kilnbakery.com/reviews/review_1", "$type": "Review", "rating": 1, "body": "Example body", "venue": "Example venue", "displayConsent": true, "status": "submitted", "customer": "customer_1" } ``` ## Relationships - A Review **evaluates** one [Offer](/business/nouns/offer): a Review evaluates one [Offer](/business/nouns/offer); Reviews of a [Product](/business/nouns/product) or [Brand](/business/nouns/brand) roll up through its Offers. `evaluates`, inverse [`reviews`](/business/nouns/offer#rel-reviews). ## Lifecycle | State | Meaning | Moves to | | --- | --- | --- | | `submitted` (first) | Written and not yet shown. | `published` by [Review.publish](/business/nouns/review/publish); `withheld` by [Review.withhold](/business/nouns/review/withhold); `removed` by [Review.remove](/business/nouns/review/remove) | | `published` | Shown on the Startup’s Pages or its venue, with its rating counted. | `withheld` by [Review.withhold](/business/nouns/review/withhold); `removed` by [Review.remove](/business/nouns/review/remove) | | `withheld` | Kept off display for a recorded reason, never for its rating. | `published` by [Review.publish](/business/nouns/review/publish); `removed` by [Review.remove](/business/nouns/review/remove) | | `removed` | Taken down for good at its author’s or its venue’s request; the record stays. | None: it ends here. | ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Review.publish](/business/nouns/review/publish) | Publish shows a Review on the Startup’s Pages with its rating counted, whatever the rating. | [Marketing Lead](/agents/marketing/marketing-lead) | [`Review.published`](/business/events/Review.published) | Two-way: `try`, `send`, `do` | | [Review.remove](/business/nouns/review/remove) | Remove takes a Review down for good when its author or its venue asks; the record is kept. | [Marketing Lead](/agents/marketing/marketing-lead) | [`Review.removed`](/business/events/Review.removed) | Two-way: `try`, `send`, `do` | | [Review.withhold](/business/nouns/review/withhold) | Withhold keeps a Review off display for one of five reasons, none of them its rating or its tone. | [Marketing Lead](/agents/marketing/marketing-lead) | [`Review.withheld`](/business/events/Review.withheld) | Two-way: `try`, `send`, `do` | | [Review.create](/business/nouns/review/create) | Creates a Review. Inherited from [Noun](/business/nouns/noun). | None. | `Review.created` | Two-way: `try`, `send`, `do` | | [Review.get](/business/nouns/review/get) | Returns one Review by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Review.list](/business/nouns/review/list) | Returns Reviews, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Review.update](/business/nouns/review/update) | Changes the given properties of a Review. Inherited from [Noun](/business/nouns/noun). | None. | `Review.updated` | Two-way: `try`, `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Review.create` | Yes | Yes | Yes | No | | `Review.get` | Yes | Yes | Yes | Yes | | `Review.list` | Yes | Yes | Yes | Yes | | `Review.update` | Yes | Yes | Yes | No | | `Review.publish` | Yes | Yes | Yes | No | | `Review.remove` | Yes | Yes | Yes | No | | `Review.withhold` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Publish the latest review. ``` **API** ```bash curl -X POST https://api.sb/patentpad.com/reviews/review_1/publish \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/patentpad.com", "review": { "$id": "https://api.sb/patentpad.com/reviews/review_1", "$type": "Review", "rating": 1, "status": "submitted" }, "action": { "$id": "https://api.sb/patentpad.com/actions/action_1", "operation": "Review.publish", "status": "done" }, "links": { "self": "https://api.sb/patentpad.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const review = await $.Review.publish({ review: 'review_1' }) ``` **CLI** ```bash npx startup-builder do Review.publish --json '{"review":"review_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Review.publish({ review: 'review_1' })" } } ``` ## Example A [Customer](/business/nouns/customer) of a dental-billing app leaves a 5-star Review on an outside venue after her first clean month. She agrees to display, so the Review also appears on the app's pricing [Page](/business/nouns/page). # publish URL: /business/nouns/review/publish · Id: `verb:Review.publish` · Call: `await $.Review.publish({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Publish shows a Review on the Startup’s Pages with its rating counted, whatever the rating. Publish shows a [Review](/business/nouns/review) on the [Startup](/business/nouns/startup)’s [Pages](/business/nouns/page) with its rating counted, whatever the rating. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `review` | [Review](/business/nouns/review) | Yes | The Review to show. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `review` | [Review](/business/nouns/review) | Yes | The Review, now `published`. | ## Effects - Emits [`Review.published`](/business/events/Review.published). - Performed by the [Marketing Lead](/agents/marketing/marketing-lead). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Adds its rating to the Product’s average on every Page that shows one. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Review.publish](/business/nouns/review/publish) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Medium: two-way, visible | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | 1 business hour, in which a watcher can pause, redirect or cancel it; then it runs. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Publish the latest review. ``` **API** ```bash curl -X POST https://api.sb/patentpad.com/reviews/review_1/publish \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/patentpad.com", "review": { "$id": "https://api.sb/patentpad.com/reviews/review_1", "$type": "Review", "rating": 1, "status": "submitted" }, "action": { "$id": "https://api.sb/patentpad.com/actions/action_1", "operation": "Review.publish", "status": "done" }, "links": { "self": "https://api.sb/patentpad.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const review = await $.Review.publish({ review: 'review_1' }) ``` **CLI** ```bash npx startup-builder do Review.publish --json '{"review":"review_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Review.publish({ review: 'review_1' })" } } ``` # remove URL: /business/nouns/review/remove · Id: `verb:Review.remove` · Call: `await $.Review.remove({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Remove takes a Review down for good when its author or its venue asks; the record is kept. Remove takes a [Review](/business/nouns/review) down for good when its author or its venue asks; the record is kept. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `review` | [Review](/business/nouns/review) | Yes | The Review to take down. | | `reason` | `string` | Yes | Who asked. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `review` | [Review](/business/nouns/review) | Yes | The Review, now `removed`. | ## Effects - Emits [`Review.removed`](/business/events/Review.removed). - Performed by the [Marketing Lead](/agents/marketing/marketing-lead). - Two-way: it runs at once, in the `try`, `send` and `do` modes. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Review.remove](/business/nouns/review/remove) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Remove the latest review. ``` **API** ```bash curl -X POST https://api.sb/petpantry.shop/reviews/review_1/remove \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"reason":"authorRequest"}' ``` ```json { "api": "https://api.sb/petpantry.shop", "review": { "$id": "https://api.sb/petpantry.shop/reviews/review_1", "$type": "Review", "rating": 1, "status": "submitted" }, "action": { "$id": "https://api.sb/petpantry.shop/actions/action_1", "operation": "Review.remove", "status": "done" }, "links": { "self": "https://api.sb/petpantry.shop/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const review = await $.Review.remove({ review: 'review_1', reason: 'authorRequest' }) ``` **CLI** ```bash npx startup-builder do Review.remove --json '{"review":"review_1","reason":"authorRequest"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Review.remove({ review: 'review_1', reason: 'authorRequest' })" } } ``` # withhold URL: /business/nouns/review/withhold · Id: `verb:Review.withhold` · Call: `await $.Review.withhold({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Withhold keeps a Review off display for one of five reasons, none of them its rating or its tone. Withhold keeps a [Review](/business/nouns/review) off display for one of five reasons, none of them its rating or its tone. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `review` | [Review](/business/nouns/review) | Yes | The Review to withhold. | | `reason` | `string` | Yes | Why it is not shown. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `review` | [Review](/business/nouns/review) | Yes | The Review, now `withheld`. | ## Effects - Emits [`Review.withheld`](/business/events/Review.withheld). - Performed by the [Marketing Lead](/agents/marketing/marketing-lead). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Records the reason beside the Review, where every reader of the record sees it. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Review.withhold](/business/nouns/review/withhold) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Withhold the latest review. ``` **API** ```bash curl -X POST https://api.sb/routewise.dev/reviews/review_1/withhold \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"reason":"fake"}' ``` ```json { "api": "https://api.sb/routewise.dev", "review": { "$id": "https://api.sb/routewise.dev/reviews/review_1", "$type": "Review", "rating": 1, "status": "submitted" }, "action": { "$id": "https://api.sb/routewise.dev/actions/action_1", "operation": "Review.withhold", "status": "done" }, "links": { "self": "https://api.sb/routewise.dev/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const review = await $.Review.withhold({ review: 'review_1', reason: 'fake' }) ``` **CLI** ```bash npx startup-builder do Review.withhold --json '{"review":"review_1","reason":"fake"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Review.withhold({ review: 'review_1', reason: 'fake' })" } } ``` # accept URL: /business/nouns/risk/accept · Id: `verb:Risk.accept` · Call: `await $.Risk.accept({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Accept records an officer’s signed Decision to carry a Risk untreated until its next review. Accept records an officer’s signed [Decision](/business/nouns/decision) to carry a [Risk](/business/nouns/risk) untreated until its next review. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `risk` | [Risk](/business/nouns/risk) | Yes | The Risk to carry. | | `reason` | `text` | Yes | Why it is carried, recorded as a Decision. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `risk` | [Risk](/business/nouns/risk) | Yes | The accepted Risk. | ## Effects - Emits [`Risk.accepted`](/business/events/Risk.accepted). - Performed by the [Founder](/agents/founding/founder). - One-way: it waits out its delay window, and runs in the `send` and `do` modes. - Needs a person: an officer signs the acceptance, part of the human floor. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Risk.accept](/business/nouns/risk/accept) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Medium: one-way, bounded | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | 1 business hour, in which a watcher can pause, redirect or cancel it; then it runs. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Accept the latest risk. ``` **API** ```bash curl -X POST https://api.sb/routewise.dev/risks/risk_1/accept \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"reason":"Example reason"}' ``` ```json { "api": "https://api.sb/routewise.dev", "risk": { "$id": "https://api.sb/routewise.dev/risks/risk_1", "$type": "Risk", "scope": "Example scope", "likelihood": 1, "impact": 1, "owner": "role_1" }, "action": { "$id": "https://api.sb/routewise.dev/actions/action_1", "operation": "Risk.accept", "status": "done" }, "links": { "self": "https://api.sb/routewise.dev/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const risk = await $.Risk.accept({ risk: 'risk_1', reason: 'Example reason' }) ``` **CLI** ```bash npx startup-builder do Risk.accept --json '{"risk":"risk_1","reason":"Example reason"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Risk.accept({ risk: 'risk_1', reason: 'Example reason' })" } } ``` # assess URL: /business/nouns/risk/assess · Id: `verb:Risk.assess` · Call: `await $.Risk.assess({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Assess scores a Risk’s likelihood and impact from the Startup’s records and sets its next review date. Assess scores a [Risk](/business/nouns/risk)’s likelihood and impact from the [Startup](/business/nouns/startup)’s records and sets its next review date. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `risk` | [Risk](/business/nouns/risk) | Yes | The Risk to score. | | `likelihood` | `integer` | Yes | Likelihood from 1 to 5. | | `impact` | `integer` | Yes | Impact from 1 to 5. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `risk` | [Risk](/business/nouns/risk) | Yes | The scored Risk. | ## Effects - Emits [`Risk.assessed`](/business/events/Risk.assessed). - Performed by the [Risk Analyst](/agents/operations/risk-analyst). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Raises the Risk to its owner when likelihood times impact reaches 12 or more. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Risk.assess](/business/nouns/risk/assess) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Assess the latest risk. ``` **API** ```bash curl -X POST https://api.sb/shiftnote.app/risks/risk_1/assess \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"likelihood":1,"impact":1}' ``` ```json { "api": "https://api.sb/shiftnote.app", "risk": { "$id": "https://api.sb/shiftnote.app/risks/risk_1", "$type": "Risk", "scope": "Example scope", "likelihood": 1, "impact": 1, "owner": "role_1" }, "action": { "$id": "https://api.sb/shiftnote.app/actions/action_1", "operation": "Risk.assess", "status": "done" }, "links": { "self": "https://api.sb/shiftnote.app/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const risk = await $.Risk.assess({ risk: 'risk_1', likelihood: 1, impact: 1 }) ``` **CLI** ```bash npx startup-builder do Risk.assess --json '{"risk":"risk_1","likelihood":1,"impact":1}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Risk.assess({ risk: 'risk_1', likelihood: 1, impact: 1 })" } } ``` # close URL: /business/nouns/risk/close · Id: `verb:Risk.close` · Call: `await $.Risk.close({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Close ends a Risk that can no longer happen and keeps it, with its scores and treatments, forever. Close ends a [Risk](/business/nouns/risk) that can no longer happen and keeps it, with its scores and treatments, forever. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `risk` | [Risk](/business/nouns/risk) | Yes | The Risk to close. | | `reason` | `text` | Yes | Why it can no longer happen. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `risk` | [Risk](/business/nouns/risk) | Yes | The closed Risk, kept forever. | ## Effects - Emits [`Risk.closed`](/business/events/Risk.closed). - Performed by the [Risk Analyst](/agents/operations/risk-analyst). - One-way: it waits out its delay window, and runs in the `send` and `do` modes. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Risk.close](/business/nouns/risk/close) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Medium: one-way, bounded | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | 1 business hour, in which a watcher can pause, redirect or cancel it; then it runs. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Close the latest risk. ``` **API** ```bash curl -X POST https://api.sb/patentpad.com/risks/risk_1/close \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"reason":"Example reason"}' ``` ```json { "api": "https://api.sb/patentpad.com", "risk": { "$id": "https://api.sb/patentpad.com/risks/risk_1", "$type": "Risk", "scope": "Example scope", "likelihood": 1, "impact": 1, "owner": "role_1" }, "action": { "$id": "https://api.sb/patentpad.com/actions/action_1", "operation": "Risk.close", "status": "done" }, "links": { "self": "https://api.sb/patentpad.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const risk = await $.Risk.close({ risk: 'risk_1', reason: 'Example reason' }) ``` **CLI** ```bash npx startup-builder do Risk.close --json '{"risk":"risk_1","reason":"Example reason"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Risk.close({ risk: 'risk_1', reason: 'Example reason' })" } } ``` # Risk URL: /business/nouns/risk · Id: `noun:risk` > A Risk is something that could harm a Startup or a Portfolio, scored by likelihood and impact, and treated, accepted, or closed. A Risk is something that could harm a [Startup](/business/nouns/startup) or a [Portfolio](/business/nouns/portfolio), scored by likelihood and impact, and treated, accepted, or closed. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `scope` | `string` | Yes | Whose Risk it is: `startup` or `portfolio`, for exposure shared across siblings. | | `likelihood` | `integer` | Yes | How likely it is within a year, from 1 (rare) to 5 (expected). | | `impact` | `integer` | Yes | How much harm it does if it happens, from 1 (minor) to 5 (ends the Startup). | | `treatment` | `string` | No | The chosen response: `treat`, `accept`, `transfer`, or `avoid`. | | `owner` | [Role](/business/nouns/role) | Yes | The Role that owns the Risk and its next review. | | `status` | `string` | Yes | `open`, `treated`, `accepted`, or `closed`. A closed Risk is kept forever. | | `reviewBy` | `date` | No | When the owner next scores it again. | ## Object ```json { "$id": "https://api.sb/ledgerlark.com/risks/risk_1", "$type": "Risk", "scope": "Example scope", "likelihood": 1, "impact": 1, "treatment": "treat", "owner": "role_1", "status": "open", "reviewBy": "2026-10-22" } ``` ## Relationships - A Risk **has** one [Portfolio](/business/nouns/portfolio): [Exposure](/business/nouns/exposure) shared across sibling [Startups](/business/nouns/startup), such as one upstream every sibling relies on. `portfolio`, inverse [`risks`](/business/nouns/portfolio#rel-risks). - A Risk **has** one [Startup](/business/nouns/startup): the Risks scored for one [Startup](/business/nouns/startup), open and closed. `startup`, inverse [`risks`](/business/nouns/startup#rel-risks). - A Risk **is treated by** many [Controls](/business/nouns/control): the [Controls](/business/nouns/control) that lower the Risk. Every Control cites the Risks it treats. `treatedBy`, inverse [`treats`](/business/nouns/control#rel-treats). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Risk.accept](/business/nouns/risk/accept) | Accept records an officer’s signed Decision to carry a Risk untreated until its next review. | [Founder](/agents/founding/founder) | [`Risk.accepted`](/business/events/Risk.accepted) | One-way: `send`, `do` | | [Risk.assess](/business/nouns/risk/assess) | Assess scores a Risk’s likelihood and impact from the Startup’s records and sets its next review date. | [Risk Analyst](/agents/operations/risk-analyst) | [`Risk.assessed`](/business/events/Risk.assessed) | Two-way: `try`, `send`, `do` | | [Risk.close](/business/nouns/risk/close) | Close ends a Risk that can no longer happen and keeps it, with its scores and treatments, forever. | [Risk Analyst](/agents/operations/risk-analyst) | [`Risk.closed`](/business/events/Risk.closed) | One-way: `send`, `do` | | [Risk.treat](/business/nouns/risk/treat) | Treat links a Risk to the Controls that lower it and records the score it should reach. | [Risk Analyst](/agents/operations/risk-analyst) | [`Risk.treated`](/business/events/Risk.treated) | Two-way: `try`, `send`, `do` | | [Risk.create](/business/nouns/risk/create) | Creates a Risk. Inherited from [Noun](/business/nouns/noun). | None. | `Risk.created` | Two-way: `try`, `send`, `do` | | [Risk.get](/business/nouns/risk/get) | Returns one Risk by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Risk.list](/business/nouns/risk/list) | Returns Risks, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Risk.update](/business/nouns/risk/update) | Changes the given properties of a Risk. Inherited from [Noun](/business/nouns/noun). | None. | `Risk.updated` | Two-way: `try`, `send`, `do` | A Risk is never deleted: it ends by [Risk.close](/business/nouns/risk/close), and its records stay. ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Risk.create` | Yes | Yes | Yes | No | | `Risk.get` | Yes | Yes | Yes | Yes | | `Risk.list` | Yes | Yes | Yes | Yes | | `Risk.update` | Yes | Yes | Yes | No | | `Risk.accept` | Yes | No | No | No | | `Risk.assess` | Yes | Yes | Yes | No | | `Risk.close` | Yes | No | No | No | | `Risk.treat` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Assess the latest risk. ``` **API** ```bash curl -X POST https://api.sb/shiftnote.app/risks/risk_1/assess \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"likelihood":1,"impact":1}' ``` ```json { "api": "https://api.sb/shiftnote.app", "risk": { "$id": "https://api.sb/shiftnote.app/risks/risk_1", "$type": "Risk", "scope": "Example scope", "likelihood": 1, "impact": 1, "owner": "role_1" }, "action": { "$id": "https://api.sb/shiftnote.app/actions/action_1", "operation": "Risk.assess", "status": "done" }, "links": { "self": "https://api.sb/shiftnote.app/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const risk = await $.Risk.assess({ risk: 'risk_1', likelihood: 1, impact: 1 }) ``` **CLI** ```bash npx startup-builder do Risk.assess --json '{"risk":"risk_1","likelihood":1,"impact":1}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Risk.assess({ risk: 'risk_1', likelihood: 1, impact: 1 })" } } ``` ## Example A [Startup](/business/nouns/startup) relies on one model upstream for every reply. The [Risk Analyst](/agents/operations/risk-analyst) records a Risk with likelihood 3 and impact 4. It treats the Risk with a failover [Control](/business/nouns/control) and sets the next review for the end of the quarter. # treat URL: /business/nouns/risk/treat · Id: `verb:Risk.treat` · Call: `await $.Risk.treat({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Treat links a Risk to the Controls that lower it and records the score it should reach. Treat links a [Risk](/business/nouns/risk) to the [Controls](/business/nouns/control) that lower it and records the score it should reach. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `risk` | [Risk](/business/nouns/risk) | Yes | The Risk to treat. | | `controls` | list of [Control](/business/nouns/control) | Yes | The Controls that lower it. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `risk` | [Risk](/business/nouns/risk) | Yes | The treated Risk. | ## Effects - Emits [`Risk.treated`](/business/events/Risk.treated). - Performed by the [Risk Analyst](/agents/operations/risk-analyst). - Two-way: it runs at once, in the `try`, `send` and `do` modes. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Risk.treat](/business/nouns/risk/treat) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Treat the latest risk with a control. ``` **API** ```bash curl -X POST https://api.sb/routewise.dev/risks/risk_1/treat \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"controls":["control_1"]}' ``` ```json { "api": "https://api.sb/routewise.dev", "risk": { "$id": "https://api.sb/routewise.dev/risks/risk_1", "$type": "Risk", "scope": "Example scope", "likelihood": 1, "impact": 1, "owner": "role_1" }, "action": { "$id": "https://api.sb/routewise.dev/actions/action_1", "operation": "Risk.treat", "status": "done" }, "links": { "self": "https://api.sb/routewise.dev/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const risk = await $.Risk.treat({ risk: 'risk_1', controls: ['control_1'] }) ``` **CLI** ```bash npx startup-builder do Risk.treat --json '{"risk":"risk_1","controls":["control_1"]}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Risk.treat({ risk: 'risk_1', controls: ['control_1'] })" } } ``` # Role Review URL: /business/nouns/role-review · Id: `noun:role-review` > A Role Review is a dated check of one Role against its contract: its results, its standards and its autonomy rung. A Role Review is a dated check of one [Role](/business/nouns/role) against its contract: its results, its standards and its autonomy rung. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `role` | [Role](/business/nouns/role) | Yes | The Role it reviews. | | `period` | `string` | Yes | The period it covers, such as `2026-W43` or `2026-10`. | | `results` | `json` | No | Each result Metric’s value against its target for the period. | | `standardsMet` | `boolean` | No | True when the seat held every standard in its contract for the period. | | `rung` | `string` | No | One of `assist`, `supervised`, or `full`: the autonomy rung the seat holds after the review. | | `change` | `text` | No | The one change the review asks for, if any. | ## Object ```json { "$id": "https://api.sb/patentpad.com/role-reviews/role_review_1", "$type": "RoleReview", "role": "role_1", "period": "2026-W43", "results": {}, "standardsMet": true, "rung": "assist", "change": "Answer weekend chats within 30 minutes." } ``` ## Relationships - A Role Review **reviews** one [Role](/business/nouns/role): each Role Review checks one [Role](/business/nouns/role), and a Role keeps every review it has had. `reviews`, inverse [`roleReviews`](/business/nouns/role#rel-role-reviews). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [RoleReview.get](/business/nouns/role-review/get) | Returns one Role Review by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [RoleReview.list](/business/nouns/role-review/list) | Returns Role Reviews, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | A Role Review is kept forever and never edited: it has no `update` or `delete`. ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `RoleReview.get` | Yes | Yes | Yes | Yes | | `RoleReview.list` | Yes | Yes | Yes | Yes | ## Call it **Ask** ```text Show me the latest role review. ``` **API** ```bash curl https://api.sb/tutorloop.com/role-reviews/role_review_1 \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/tutorloop.com", "$type": "RoleReview", "$id": "https://api.sb/tutorloop.com/role-reviews/role_review_1", "roleReview": { "$id": "https://api.sb/tutorloop.com/role-reviews/role_review_1", "$type": "RoleReview", "role": "role_1", "period": "2026-W43" }, "links": { "self": "https://api.sb/tutorloop.com/role-reviews/role_review_1", "up": "https://api.sb/tutorloop.com/role-reviews" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const roleReview = await $.RoleReview.get({ id: 'role_review_1' }) ``` **CLI** ```bash npx startup-builder do RoleReview.get --json '{"id":"role_review_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.RoleReview.get({ id: 'role_review_1' })" } } ``` ## Example Each week the [Founder](/agents/founding/founder) seat calls [`Role.review`](/business/nouns/role/review) for the [Customer Lead](/agents/customer/customer-lead). In `2026-W43` it finds 97 percent of first responses on time and every standard held. The seat stays on `supervised`, with one ask: answer weekend chats within 30 minutes. # Role URL: /business/nouns/role · Id: `noun:role` > A Role is a seat that owns a set of work and holds the Permissions to do it, filled by a Human or an Agent. A Role is a seat that owns a set of work and holds the [Permissions](/business/nouns/permission) to do it, filled by a [Human](/business/nouns/human) or an [Agent](/business/nouns/agent). The work and its Permissions stay with the seat when a new filler takes it. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `name` | `string` | Yes | The title of the seat. | | `responsibilities` | `text` | No | The work the seat owns. | | `status` | `string` | Yes | One of `vacant` or `filled`. | | `autonomy` | `json` | No | How much its agent does without asking: a rung, `assist`, `supervised` or `full`, with another rung per decision class where it differs. | ## Object ```json { "$id": "https://api.sb/kilnbakery.com/roles/role_1", "$type": "Role", "name": "Kiln Bakery", "responsibilities": "Example responsibilities", "status": "vacant", "autonomy": { "default": "supervised", "byClass": { "high": "assist" } } } ``` ## Relationships - A Role **is filled by** many [Workers](/business/nouns/worker): a [Worker](/business/nouns/worker), human or agent, fills a Role and acts under its [Permissions](/business/nouns/permission); one [Agent](/business/nouns/agent) can fill Roles in many [Startups](/business/nouns/startup). `filledBy`, inverse [`fills`](/business/nouns/worker#rel-fills). - A Role **holds** many [Permissions](/business/nouns/permission): a Role’s [Permissions](/business/nouns/permission) are what its [Worker](/business/nouns/worker) may do: [Verbs](/business/nouns/verb) on [Nouns](/business/nouns/noun) within a scope and a [Limit](/business/nouns/limit). `holds`, inverse [`heldBy`](/business/nouns/permission#rel-held-by). - A Role **has** many [Openings](/business/nouns/opening): an [Opening](/business/nouns/opening) is a need for a [Human](/business/nouns/human) in one Role, taking a share of that Role’s work. `openings`, inverse [`staffs`](/business/nouns/opening#rel-staffs). - A Role **has** many [Personas](/business/nouns/persona): the Role whose [Permissions](/business/nouns/permission) a [Persona](/business/nouns/persona) signs in with, so an [App](/business/nouns/app) compiles its [Dashboards](/business/nouns/dashboard) and [Verbs](/business/nouns/verb) from one record. `personas`, inverse [`holds`](/business/nouns/persona#rel-holds). - A Role **requires** many [Skills](/business/nouns/skill): the [Skills](/business/nouns/skill), each at a level, a [Worker](/business/nouns/worker) needs to fill the Role. `requires`, inverse [`requiredBy`](/business/nouns/skill#rel-required-by). - A Role **has** many [Role Reviews](/business/nouns/role-review): each [Role Review](/business/nouns/role-review) checks one Role, and a Role keeps every review it has had. `roleReviews`, inverse [`reviews`](/business/nouns/role-review#rel-reviews). - A Role **has** one [Team](/business/nouns/team): a [Team](/business/nouns/team) groups the Roles that do one kind of work under one owner. `team`, inverse [`groups`](/business/nouns/team#rel-groups). ## Lifecycle | State | Meaning | Moves to | | --- | --- | --- | | `vacant` (first) | No Worker fills it, so its work waits for the Role above. | `filled` by [Role.staff](/business/nouns/role/staff) | | `filled` | A Human or an Agent fills it and performs its Verbs under its Permissions. | `vacant` by [Role.vacate](/business/nouns/role/vacate); `vacant` on [`Agent.retired`](/business/events/Agent.retired) when the Agent filling this Role is retired; `vacant` on `Agent.deleted` when the Agent filling this Role is deleted; `vacant` on `Human.deleted` when the Human filling this Role is deleted | ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Role.review](/business/nouns/role/review) | Review checks one Role against its contract for a period and records a Role Review. | [Founder](/agents/founding/founder) | [`Role.reviewed`](/business/events/Role.reviewed) | Two-way: `try`, `send`, `do` | | [Role.staff](/business/nouns/role/staff) | Staff fills a Role with a Worker, human or agent, who then performs the Role’s Verbs under its Permissions. | [People Lead](/agents/people/people-lead) | [`Role.staffed`](/business/events/Role.staffed) | None. | | [Role.vacate](/business/nouns/role/vacate) | Vacate takes the Worker out of a Role, and the seat’s Tasks route to the Role it escalates to until a new Worker is staffed. | [People Lead](/agents/people/people-lead) | [`Role.vacated`](/business/events/Role.vacated) | Two-way: `try`, `send`, `do` | | [Role.create](/business/nouns/role/create) | Creates a Role. Inherited from [Noun](/business/nouns/noun). | None. | `Role.created` | Two-way: `try`, `send`, `do` | | [Role.get](/business/nouns/role/get) | Returns one Role by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Role.list](/business/nouns/role/list) | Returns Roles, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Role.update](/business/nouns/role/update) | Changes the given properties of a Role. Inherited from [Noun](/business/nouns/noun). | None. | `Role.updated` | Two-way: `try`, `send`, `do` | | [Role.delete](/business/nouns/role/delete) | Deletes a Role; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Role.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Role.create` | Yes | Yes | No | No | | `Role.get` | Yes | Yes | Yes | Yes | | `Role.list` | Yes | Yes | Yes | Yes | | `Role.update` | Yes | Yes | No | No | | `Role.delete` | Yes | Yes | No | No | | `Role.review` | Yes | Yes | No | No | | `Role.staff` | Yes | Yes | No | No | | `Role.vacate` | Yes | Yes | No | No | ## Call it **Ask** ```text Staff the latest role with a worker. ``` **API** ```bash curl -X POST https://api.sb/kilnbakery.com/roles/role_1/staff \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"worker":"worker_1"}' ``` ```json { "api": "https://api.sb/kilnbakery.com", "role": { "$id": "https://api.sb/kilnbakery.com/roles/role_1", "$type": "Role", "name": "Kiln Bakery", "status": "vacant" }, "action": { "$id": "https://api.sb/kilnbakery.com/actions/action_1", "operation": "Role.staff", "status": "done" }, "links": { "self": "https://api.sb/kilnbakery.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const role = await $.Role.staff({ role: 'role_1', worker: 'worker_1' }) ``` **CLI** ```bash npx startup-builder do Role.staff --json '{"role":"role_1","worker":"worker_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Role.staff({ role: 'role_1', worker: 'worker_1' })" } } ``` ## Example The [Customer Lead](/agents/customer/customer-lead) Role at a tutoring marketplace owns first replies and refunds under $100. An Agent fills it on weekdays and the [Founder](/agents/founding/founder) on weekends; the $100 refund [Limit](/business/nouns/limit) binds both. # review URL: /business/nouns/role/review · Id: `verb:Role.review` · Call: `await $.Role.review({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Review checks one Role against its contract for a period and records a Role Review. [Review](/business/nouns/review) checks one [Role](/business/nouns/role) against its contract for a period and records a [Role Review](/business/nouns/role-review). ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `role` | [Role](/business/nouns/role) | Yes | The Role to review. | | `period` | `string` | Yes | The period it covers, such as `2026-W43`. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `role` | [Role](/business/nouns/role) | Yes | The reviewed Role. | | `roleReview` | [Role Review](/business/nouns/role-review) | Yes | The recorded Role Review. | ## Effects - Emits [`Role.reviewed`](/business/events/Role.reviewed). - Performed by the [Founder](/agents/founding/founder). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Moves the seat down one autonomy rung when it missed a standard; it moves up only on its Evaluators’ agreement. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Role.review](/business/nouns/role/review) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Review the latest role. ``` **API** ```bash curl -X POST https://api.sb/kilnbakery.com/roles/role_1/review \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"period":"Example period"}' ``` ```json { "api": "https://api.sb/kilnbakery.com", "role": { "$id": "https://api.sb/kilnbakery.com/roles/role_1", "$type": "Role", "name": "Kiln Bakery", "status": "vacant" }, "roleReview": { "$id": "https://api.sb/kilnbakery.com/role-reviews/role_review_1", "$type": "RoleReview", "role": "role_1", "period": "2026-W43" }, "action": { "$id": "https://api.sb/kilnbakery.com/actions/action_1", "operation": "Role.review", "status": "done" }, "links": { "self": "https://api.sb/kilnbakery.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { role, roleReview } = await $.Role.review({ role: 'role_1', period: 'Example period' }) ``` **CLI** ```bash npx startup-builder do Role.review --json '{"role":"role_1","period":"Example period"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Role.review({ role: 'role_1', period: 'Example period' })" } } ``` Guides that call it: [Review the support agent](/agents/review-a-role). # staff URL: /business/nouns/role/staff · Id: `verb:Role.staff` · Call: `await $.Role.staff({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Staff fills a Role with a Worker, human or agent, who then performs the Role’s Verbs under its Permissions. Staff fills a [Role](/business/nouns/role) with a [Worker](/business/nouns/worker), human or agent, who then performs the Role’s [Verbs](/business/nouns/verb) under its [Permissions](/business/nouns/permission). ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `role` | [Role](/business/nouns/role) | Yes | The Role to fill. | | `worker` | [Worker](/business/nouns/worker) | Yes | The Worker who fills it. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `role` | [Role](/business/nouns/role) | Yes | The staffed Role. | ## Effects - Emits [`Role.staffed`](/business/events/Role.staffed). - Performed by the [People Lead](/agents/people/people-lead). - Gives a new agent Worker its name for this Startup. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Role.staff](/business/nouns/role/staff) | | The record is not in a state that allows this Verb, so the call is refused. | [`refused`](/code/api/errors/refused) | Read the record, run the Verb that moves it to an allowed state, then retry. | [Role.staff](/business/nouns/role/staff) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Staff the latest role with a worker. ``` **API** ```bash curl -X POST https://api.sb/kilnbakery.com/roles/role_1/staff \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"worker":"worker_1"}' ``` ```json { "api": "https://api.sb/kilnbakery.com", "role": { "$id": "https://api.sb/kilnbakery.com/roles/role_1", "$type": "Role", "name": "Kiln Bakery", "status": "vacant" }, "action": { "$id": "https://api.sb/kilnbakery.com/actions/action_1", "operation": "Role.staff", "status": "done" }, "links": { "self": "https://api.sb/kilnbakery.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const role = await $.Role.staff({ role: 'role_1', worker: 'worker_1' }) ``` **CLI** ```bash npx startup-builder do Role.staff --json '{"role":"role_1","worker":"worker_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Role.staff({ role: 'role_1', worker: 'worker_1' })" } } ``` Guides that call it: [Run sales myself](/agents/run-a-seat-yourself), [Add a role to the team](/agents/add-a-role), [Add a team](/agents/add-a-team), [Buy a specialist agent for a seat](/agents/buy-a-specialist-agent-for-a-seat). # vacate URL: /business/nouns/role/vacate · Id: `verb:Role.vacate` · Call: `await $.Role.vacate({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Vacate takes the Worker out of a Role, and the seat’s Tasks route to the Role it escalates to until a new Worker is staffed. Vacate takes the [Worker](/business/nouns/worker) out of a [Role](/business/nouns/role), and the seat’s [Tasks](/business/nouns/task) route to the Role it escalates to until a new Worker is staffed. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `role` | [Role](/business/nouns/role) | Yes | The Role to empty. | | `reason` | `text` | No | Why the seat empties. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `role` | [Role](/business/nouns/role) | Yes | The vacant Role. | ## Effects - Emits [`Role.vacated`](/business/events/Role.vacated). - Performed by the [People Lead](/agents/people/people-lead). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Keeps the Role contract, its Processes and its Mailbox, so the next Worker inherits them unchanged. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Role.vacate](/business/nouns/role/vacate) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Vacate the latest role. ``` **API** ```bash curl -X POST https://api.sb/tutorloop.com/roles/role_1/vacate \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/tutorloop.com", "role": { "$id": "https://api.sb/tutorloop.com/roles/role_1", "$type": "Role", "name": "TutorLoop", "status": "vacant" }, "action": { "$id": "https://api.sb/tutorloop.com/actions/action_1", "operation": "Role.vacate", "status": "done" }, "links": { "self": "https://api.sb/tutorloop.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const role = await $.Role.vacate({ role: 'role_1' }) ``` **CLI** ```bash npx startup-builder do Role.vacate --json '{"role":"role_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Role.vacate({ role: 'role_1' })" } } ``` Next: [`Worker.delete`](/business/nouns/worker/delete) (in `guide:remove-a-teammate`). Guides that call it: [Remove a teammate](/agents/remove-a-teammate). # Screening URL: /business/nouns/screening · Id: `noun:screening` > A Screening is one check of a Party against official registers and restricted-party lists, with each list’s version, any matches and the outcome. A Screening is one check of a [Party](/business/nouns/party) against official registers and restricted-party lists, with each list’s version, any matches and the outcome. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `lists` | `json` | Yes | Each register or list checked, with the version read, such as a sanctions list dated 2026-10-20. | | `matches` | `json` | No | Each entry that resembled the Party, with the list it came from and how closely it matched. | | `outcome` | `string` | Yes | `clear` lets money move; `match` holds pending Orders; `review` opens an Approval. Never randomized. | | `via` | `string` | Yes | `platform` for a Startup-side screen; `stripe` for Stripe’s own verification result, recorded on the same Party. | ## Object ```json { "$id": "https://api.sb/quietcopy.com/screenings/screening_1", "$type": "Screening", "lists": {}, "matches": {}, "outcome": "clear", "via": "platform" } ``` ## Relationships - A Screening **screens** one [Party](/business/nouns/party): a [Party](/business/nouns/party) is screened before its first money move and again when its details change; every result stays. `screens`, inverse [`screenings`](/business/nouns/party#rel-screenings). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Screening.get](/business/nouns/screening/get) | Returns one Screening by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Screening.list](/business/nouns/screening/list) | Returns Screenings, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | A Screening is kept forever and never edited: it has no `update` or `delete`. ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Screening.get` | Yes | Yes | Yes | Yes | | `Screening.list` | Yes | Yes | Yes | Yes | ## Call it **Ask** ```text Show me the latest screening. ``` **API** ```bash curl https://api.sb/petpantry.shop/screenings/screening_1 \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/petpantry.shop", "$type": "Screening", "$id": "https://api.sb/petpantry.shop/screenings/screening_1", "screening": { "$id": "https://api.sb/petpantry.shop/screenings/screening_1", "$type": "Screening", "lists": {}, "outcome": "clear", "via": "platform" }, "links": { "self": "https://api.sb/petpantry.shop/screenings/screening_1", "up": "https://api.sb/petpantry.shop/screenings" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const screening = await $.Screening.get({ id: 'screening_1' }) ``` **CLI** ```bash npx startup-builder do Screening.get --json '{"id":"screening_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Screening.get({ id: 'screening_1' })" } } ``` ## Example A new buyer at a data marketplace places a $12,000 [Order](/business/nouns/order). The Screening checks three sanctions lists, finds no match, and records the outcome clear, so the charge proceeds. # Secret URL: /business/nouns/secret · Id: `noun:secret` > A Secret is a named credential stored write-only per environment and filled into a call at run time, never read back by a Worker. A Secret is a named credential stored write-only per environment and filled into a call at run time, never read back by a [Worker](/business/nouns/worker). ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `name` | `string` | Yes | The name a Function declares, such as `MAPS_KEY`; `list` returns names only. | | `environment` | `string` | Yes | The environment that holds this value; a Function deploys to `live` only when every declared Secret exists there. | | `scope` | `string` | Yes | Whether the whole Startup or one Tenant holds it. | | `rotatedAt` | `datetime` | No | When the value last changed. | ## Object ```json { "$id": "https://api.sb/kilnbakery.com/secrets/secret_1", "$type": "Secret", "name": "MAPS_KEY", "environment": "test", "scope": "startup", "rotatedAt": "2026-10-22T12:00:00Z" } ``` ## Relationships - A Secret **is used by** many [Functions](/business/nouns/function): a [Function](/business/nouns/function) declares the Secrets it reads; deploying to `live` fails when one is missing there. `usedBy`, inverse [`uses`](/business/nouns/function#rel-uses). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Secret.revoke](/business/nouns/secret/revoke) | Revoke ends a Secret so no call fills it again; the record and its history stay. | [Security Engineer](/agents/engineering/security-engineer) | [`Secret.revoked`](/business/events/Secret.revoked) | One-way (customer): `send`, `do` | | [Secret.rotate](/business/nouns/secret/rotate) | Rotate replaces a Secret’s value, and calls already running finish on the old one. | [Security Engineer](/agents/engineering/security-engineer) | [`Secret.rotated`](/business/events/Secret.rotated) | Two-way: `try`, `send`, `do` | | [Secret.store](/business/nouns/secret/store) | Store writes a Secret’s value for one environment; the value is never returned by any Interface. | [Security Engineer](/agents/engineering/security-engineer) | [`Secret.stored`](/business/events/Secret.stored) | Two-way: `try`, `send`, `do` | | [Secret.get](/business/nouns/secret/get) | Returns one Secret by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Secret.list](/business/nouns/secret/list) | Returns Secrets, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | A Secret is never deleted: it ends by [Secret.revoke](/business/nouns/secret/revoke), and its records stay. ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Secret.get` | Yes | Yes | Yes | Yes | | `Secret.list` | Yes | Yes | Yes | Yes | | `Secret.revoke` | Yes | No | No | No | | `Secret.rotate` | Yes | Yes | No | No | | `Secret.store` | Yes | Yes | No | No | ## Call it **Ask** ```text Store the secret “MAPS_KEY”. ``` **API** ```bash curl -X POST https://api.sb/shiftnote.app/secrets/store \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"name":"MAPS_KEY","value":"Example value","environment":"test"}' ``` ```json { "api": "https://api.sb/shiftnote.app", "secret": { "$id": "https://api.sb/shiftnote.app/secrets/secret_1", "$type": "Secret", "name": "MAPS_KEY", "environment": "test", "scope": "startup" }, "action": { "$id": "https://api.sb/shiftnote.app/actions/action_1", "operation": "Secret.store", "status": "done" }, "links": { "self": "https://api.sb/shiftnote.app/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const secret = await $.Secret.store({ name: 'MAPS_KEY', value: 'Example value', environment: 'test' }) ``` **CLI** ```bash npx startup-builder do Secret.store --json '{"name":"MAPS_KEY","value":"Example value","environment":"test"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Secret.store({ name: 'MAPS_KEY', value: 'Example value', environment: 'test' })" } } ``` ## Example A delivery app's [Function](/business/nouns/function) declares `MAPS_KEY`. The key is stored once in the test environment and once in live, and the Function deploys to live only after both exist. # revoke URL: /business/nouns/secret/revoke · Id: `verb:Secret.revoke` · Call: `await $.Secret.revoke({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Revoke ends a Secret so no call fills it again; the record and its history stay. Revoke ends a [Secret](/business/nouns/secret) so no call fills it again; the record and its history stay. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `secret` | [Secret](/business/nouns/secret) | Yes | The Secret to revoke. | | `reason` | `text` | No | Why, such as a leaked value. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `secret` | [Secret](/business/nouns/secret) | Yes | The revoked Secret. | ## Effects - Emits [`Secret.revoked`](/business/events/Secret.revoked). - Performed by the [Security Engineer](/agents/engineering/security-engineer). - One-way (customer): it waits out its delay window, and runs in the `send` and `do` modes. - A leaked value revokes at once: a brake never waits. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Secret.revoke](/business/nouns/secret/revoke) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Medium: one-way, bounded (customer) | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | 1 business hour, in which a watcher can pause, redirect or cancel it; then it runs. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Revoke the latest secret. ``` **API** ```bash curl -X POST https://api.sb/tutorloop.com/secrets/secret_1/revoke \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/tutorloop.com", "secret": { "$id": "https://api.sb/tutorloop.com/secrets/secret_1", "$type": "Secret", "name": "MAPS_KEY", "environment": "test", "scope": "startup" }, "action": { "$id": "https://api.sb/tutorloop.com/actions/action_1", "operation": "Secret.revoke", "status": "done" }, "links": { "self": "https://api.sb/tutorloop.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const secret = await $.Secret.revoke({ secret: 'secret_1' }) ``` **CLI** ```bash npx startup-builder do Secret.revoke --json '{"secret":"secret_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Secret.revoke({ secret: 'secret_1' })" } } ``` # rotate URL: /business/nouns/secret/rotate · Id: `verb:Secret.rotate` · Call: `await $.Secret.rotate({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Rotate replaces a Secret’s value, and calls already running finish on the old one. Rotate replaces a [Secret](/business/nouns/secret)’s value, and calls already running finish on the old one. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `secret` | [Secret](/business/nouns/secret) | Yes | The Secret to rotate. | | `value` | `string` | No | The new value; omitted when the upstream issues one. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `secret` | [Secret](/business/nouns/secret) | Yes | The Secret, with its new `rotatedAt`. | ## Effects - Emits [`Secret.rotated`](/business/events/Secret.rotated). - Performed by the [Security Engineer](/agents/engineering/security-engineer). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - The `secret-rotation` Control tests this Verb. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Secret.rotate](/business/nouns/secret/rotate) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Rotate the latest secret. ``` **API** ```bash curl -X POST https://api.sb/ledgerlark.com/secrets/secret_1/rotate \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/ledgerlark.com", "secret": { "$id": "https://api.sb/ledgerlark.com/secrets/secret_1", "$type": "Secret", "name": "MAPS_KEY", "environment": "test", "scope": "startup" }, "action": { "$id": "https://api.sb/ledgerlark.com/actions/action_1", "operation": "Secret.rotate", "status": "done" }, "links": { "self": "https://api.sb/ledgerlark.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const secret = await $.Secret.rotate({ secret: 'secret_1' }) ``` **CLI** ```bash npx startup-builder do Secret.rotate --json '{"secret":"secret_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Secret.rotate({ secret: 'secret_1' })" } } ``` # store URL: /business/nouns/secret/store · Id: `verb:Secret.store` · Call: `await $.Secret.store({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Store writes a Secret’s value for one environment; the value is never returned by any Interface. Store writes a [Secret](/business/nouns/secret)’s value for one environment; the value is never returned by any [Interface](/business/nouns/interface). ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `name` | `string` | Yes | The name Functions declare. | | `value` | `string` | Yes | The credential; write-only. | | `environment` | `string` | Yes | Where it holds. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `secret` | [Secret](/business/nouns/secret) | Yes | The Secret, without its value. | ## Effects - Emits [`Secret.stored`](/business/events/Secret.stored). - Performed by the [Security Engineer](/agents/engineering/security-engineer). - Two-way: it runs at once, in the `try`, `send` and `do` modes. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Secret.store](/business/nouns/secret/store) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Store the secret “MAPS_KEY”. ``` **API** ```bash curl -X POST https://api.sb/shiftnote.app/secrets/store \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"name":"MAPS_KEY","value":"Example value","environment":"test"}' ``` ```json { "api": "https://api.sb/shiftnote.app", "secret": { "$id": "https://api.sb/shiftnote.app/secrets/secret_1", "$type": "Secret", "name": "MAPS_KEY", "environment": "test", "scope": "startup" }, "action": { "$id": "https://api.sb/shiftnote.app/actions/action_1", "operation": "Secret.store", "status": "done" }, "links": { "self": "https://api.sb/shiftnote.app/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const secret = await $.Secret.store({ name: 'MAPS_KEY', value: 'Example value', environment: 'test' }) ``` **CLI** ```bash npx startup-builder do Secret.store --json '{"name":"MAPS_KEY","value":"Example value","environment":"test"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Secret.store({ name: 'MAPS_KEY', value: 'Example value', environment: 'test' })" } } ``` # Sequence URL: /business/nouns/sequence · Id: `noun:sequence` > A Sequence is a timed series of steps run for one Contact at a time: send a Message, wait, branch, or stop. A Sequence is a timed series of steps run for one [Contact](/business/nouns/contact) at a time: send a [Message](/business/nouns/message), wait, branch, or stop. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `steps` | `json` | Yes | The steps, waits, and branches. | | `exitOn` | `string` | No | The Events that end it from any step, such as a reply or a purchase. | ## Object ```json { "$id": "https://api.sb/patentpad.com/sequences/sequence_1", "$type": "Sequence", "steps": {}, "exitOn": "Example exit on" } ``` ## Relationships - A Sequence **has** many [Enrollments](/business/nouns/enrollment): the Sequence whose steps this [Enrollment](/business/nouns/enrollment) walks, one step at a time. `enrollments`, inverse [`follows`](/business/nouns/enrollment#rel-follows). - A Sequence **enrolls** many [Contacts](/business/nouns/contact): a Sequence runs for an enrolled [Contact](/business/nouns/contact) until a reply, a purchase, or another exit [Event](/business/nouns/event) ends it. `enrolls`, inverse [`enrolledIn`](/business/nouns/contact#rel-enrolled-in). - A Sequence **nurtures** many [Funnels](/business/nouns/funnel): a [Funnel](/business/nouns/funnel) follows up with each new [Lead](/business/nouns/lead) through Sequences after the opt-in. `nurtures`, inverse [`nurturesWith`](/business/nouns/funnel#rel-nurtures-with). - A Sequence **schedules** many [Messages](/business/nouns/message): a Sequence sends [Messages](/business/nouns/message), each at its own step and wait. `schedules`, inverse [`scheduledBy`](/business/nouns/message#rel-scheduled-by). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Sequence.create](/business/nouns/sequence/create) | Creates a Sequence. Inherited from [Noun](/business/nouns/noun). | None. | `Sequence.created` | Two-way: `try`, `send`, `do` | | [Sequence.get](/business/nouns/sequence/get) | Returns one Sequence by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Sequence.list](/business/nouns/sequence/list) | Returns Sequences, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Sequence.update](/business/nouns/sequence/update) | Changes the given properties of a Sequence. Inherited from [Noun](/business/nouns/noun). | None. | `Sequence.updated` | Two-way: `try`, `send`, `do` | | [Sequence.delete](/business/nouns/sequence/delete) | Deletes a Sequence; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Sequence.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Sequence.create` | Yes | Yes | Yes | No | | `Sequence.get` | Yes | Yes | Yes | Yes | | `Sequence.list` | Yes | Yes | Yes | Yes | | `Sequence.update` | Yes | Yes | Yes | No | | `Sequence.delete` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Add a sequence to ShiftNote. ``` **API** ```bash curl -X POST https://api.sb/shiftnote.app/sequences \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"steps":{}}' ``` ```json { "api": "https://api.sb/shiftnote.app", "sequence": { "$id": "https://api.sb/shiftnote.app/sequences/sequence_1", "$type": "Sequence", "steps": {} }, "action": { "$id": "https://api.sb/shiftnote.app/actions/action_1", "operation": "Sequence.create", "status": "done" }, "links": { "self": "https://api.sb/shiftnote.app/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const sequence = await $.Sequence.create({ steps: {} }) ``` **CLI** ```bash npx startup-builder do Sequence.create --json '{"steps":{}}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Sequence.create({ steps: {} })" } } ``` ## Example A trial Sequence sends a welcome Message, waits 3 days, then sends a setup tip only if the Contact has made no API call. # Service URL: /business/nouns/service · Id: `noun:service` > A Service is a Product that warrants an outcome, delivered by Agents and Humans under an Outcome Contract. A Service is a [Product](/business/nouns/product) that warrants an outcome, delivered by [Agents](/business/nouns/agent) and [Humans](/business/nouns/human) under an [Outcome Contract](/business/nouns/outcome-contract). ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `floor` | `string` | No | The human floor: `none`, `sign`, or `practice`. |
Inherited from [Product](/business/nouns/product): 3 properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `name` | `string` | Yes | The name of the Product. | | `promise` | `text` | Yes | What the Customer can rely on. | | `status` | `string` | Yes | One of `draft`, `selling` or `retired`, set by its Offers. |
## Object ```json { "$id": "https://api.sb/routewise.dev/services/service_1", "$type": "Service", "name": "RouteWise", "promise": "A route plan for 500 stops in under two seconds.", "status": "draft", "floor": "none" } ``` ## Relationships - A Service **requires** many [Workers](/business/nouns/worker): a Service’s outcome is delivered by the [Agents](/business/nouns/agent) and [Humans](/business/nouns/human) who fill its [Roles](/business/nouns/role). `requires`, inverse [`staffs`](/business/nouns/worker#rel-staffs). - A Service **is supplied by** many [Suppliers](/business/nouns/supplier): [Suppliers](/business/nouns/supplier) staff Services through the [Startup](/business/nouns/startup)’s human supply. `suppliedBy`, inverse [`delivers`](/business/nouns/supplier#rel-delivers). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Service.create](/business/nouns/service/create) | Creates a Service. Inherited from [Noun](/business/nouns/noun). | None. | `Service.created` | Two-way: `try`, `send`, `do` | | [Service.get](/business/nouns/service/get) | Returns one Service by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Service.list](/business/nouns/service/list) | Returns Services, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Service.update](/business/nouns/service/update) | Changes the given properties of a Service. Inherited from [Noun](/business/nouns/noun). | None. | `Service.updated` | Two-way: `try`, `send`, `do` | | [Service.delete](/business/nouns/service/delete) | Deletes a Service; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Service.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Service.create` | Yes | Yes | Yes | No | | `Service.get` | Yes | Yes | Yes | Yes | | `Service.list` | Yes | Yes | Yes | Yes | | `Service.update` | Yes | Yes | Yes | No | | `Service.delete` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Add a service to LedgerLark. ``` **API** ```bash curl -X POST https://api.sb/ledgerlark.com/services \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"name":"LedgerLark","promise":"Books closed by the fifth of each month."}' ``` ```json { "api": "https://api.sb/ledgerlark.com", "service": { "$id": "https://api.sb/ledgerlark.com/services/service_1", "$type": "Service", "name": "LedgerLark", "promise": "Books closed by the fifth of each month.", "status": "draft" }, "action": { "$id": "https://api.sb/ledgerlark.com/actions/action_1", "operation": "Service.create", "status": "done" }, "links": { "self": "https://api.sb/ledgerlark.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const service = await $.Service.create({ name: 'LedgerLark', promise: 'Books closed by the fifth of each month.' }) ``` **CLI** ```bash npx startup-builder do Service.create --json '{"name":"LedgerLark","promise":"Books closed by the fifth of each month."}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Service.create({ name: 'LedgerLark', promise: 'Books closed by the fifth of each month.' })" } } ``` ## Example A bookkeeping Service warrants a reconciled month by the fifth working day. Agents do the matching, and a Human accountant reviews exceptions. # Setting URL: /business/nouns/setting · Id: `noun:setting` > A Setting is a configurable value a Thing inherits from its nearest holder, Studio to Startup to Product, unless it sets its own. A Setting is a configurable value a [Thing](/business/nouns/thing) inherits from its nearest holder, [Studio](/business/nouns/studio) to [Startup](/business/nouns/startup) to [Product](/business/nouns/product), unless it sets its own. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `key` | `string` | Yes | The name of the choice. | | `value` | `json` | Yes | The chosen value. | | `locked` | `boolean` | No | True when no holder below may override it. | ## Object ```json { "$id": "https://api.sb/tutorloop.com/settings/setting_1", "$type": "Setting", "key": "Example key", "value": {}, "locked": true } ``` ## Relationships - A Setting **configures** one [Thing](/business/nouns/thing): the [Thing](/business/nouns/thing) whose choice a Setting holds; everything below it inherits the value unless it sets its own. `configures`, inverse [`configuredBy`](/business/nouns/thing#rel-configured-by). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Setting.create](/business/nouns/setting/create) | Creates a Setting. Inherited from [Noun](/business/nouns/noun). | None. | `Setting.created` | Two-way: `try`, `send`, `do` | | [Setting.get](/business/nouns/setting/get) | Returns one Setting by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Setting.list](/business/nouns/setting/list) | Returns Settings, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Setting.update](/business/nouns/setting/update) | Changes the given properties of a Setting. Inherited from [Noun](/business/nouns/noun). | None. | `Setting.updated` | Two-way: `try`, `send`, `do` | | [Setting.delete](/business/nouns/setting/delete) | Deletes a Setting; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Setting.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Setting.create` | Yes | Yes | No | No | | `Setting.get` | Yes | Yes | Yes | Yes | | `Setting.list` | Yes | Yes | Yes | Yes | | `Setting.update` | Yes | Yes | No | No | | `Setting.delete` | Yes | Yes | No | No | ## Call it **Ask** ```text Add a setting to QuietCopy. ``` **API** ```bash curl -X POST https://api.sb/quietcopy.com/settings \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"key":"Example key","value":{}}' ``` ```json { "api": "https://api.sb/quietcopy.com", "setting": { "$id": "https://api.sb/quietcopy.com/settings/setting_1", "$type": "Setting", "key": "Example key", "value": {} }, "action": { "$id": "https://api.sb/quietcopy.com/actions/action_1", "operation": "Setting.create", "status": "done" }, "links": { "self": "https://api.sb/quietcopy.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const setting = await $.Setting.create({ key: 'Example key', value: {} }) ``` **CLI** ```bash npx startup-builder do Setting.create --json '{"key":"Example key","value":{}}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Setting.create({ key: 'Example key', value: {} })" } } ``` ## Example The Studio sets the default currency to USD. A Startup selling in euros overrides it with EUR, and its Products inherit EUR. # Share URL: /business/nouns/share · Id: `noun:share` > A Share is a unit of ownership in a Company, of one class, held by one Holder. A Share is a unit of ownership in a [Company](/business/nouns/company), of one class, held by one [Holder](/business/nouns/holder). ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `class` | `string` | Yes | The share class, such as common or preferred. | | `quantity` | `integer` | Yes | How many units the record holds. | | `price` | `money` | No | The price paid per unit at issue. | | `issuedAt` | `datetime` | No | When the Company issued it. | | `certificate` | [File](/business/nouns/file) | No | The certificate or book-entry File. | ## Object ```json { "$id": "https://api.sb/patentpad.com/shares/share_1", "$type": "Share", "class": "common", "quantity": 1, "price": { "amount": 499, "currency": "USD" }, "issuedAt": "2026-10-22T12:00:00Z", "certificate": "file_1" } ``` ## Relationships - A Share **is held by** one [Holder](/business/nouns/holder): each Share record belongs to one [Holder](/business/nouns/holder); a transfer writes a new record for the new Holder. `heldBy`, inverse [`shares`](/business/nouns/holder#rel-shares). - A Share **is issued by** one [Company](/business/nouns/company): a Share is issued by one [Company](/business/nouns/company) and sits on that Company’s cap table. `issuedBy`, inverse [`shares`](/business/nouns/company#rel-shares). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Share.issue](/business/nouns/share/issue) | Issue records new Shares of one class to a Holder under a board-approved Agreement, with the certificate or book entry. | [Legal Lead](/agents/legal/legal-lead) | [`Share.issued`](/business/events/Share.issued) | One-way (money): `send`, `do` | | [Share.transfer](/business/nouns/share/transfer) | Transfer moves Shares from one Holder to another under a signed Agreement, within the Company’s transfer restrictions. | [Legal Lead](/agents/legal/legal-lead) | [`Share.transferred`](/business/events/Share.transferred) | One-way: `send`, `do` | | [Share.get](/business/nouns/share/get) | Returns one Share by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Share.list](/business/nouns/share/list) | Returns Shares, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | A Share is kept forever and never edited: it has no `update` or `delete`. ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Share.get` | Yes | Yes | Yes | Yes | | `Share.list` | Yes | Yes | Yes | Yes | | `Share.issue` | Yes | No | No | No | | `Share.transfer` | Yes | No | No | No | ## Call it **Ask** ```text Issue the latest share with a holder and an agreement. ``` **API** ```bash curl -X POST https://api.sb/kilnbakery.com/shares/issue \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"holder":"holder_1","class":"Example class","quantity":1,"price":{"amount":9,"currency":"USD"},"agreement":"agreement_1"}' ``` ```json { "api": "https://api.sb/kilnbakery.com", "share": { "$id": "https://api.sb/kilnbakery.com/shares/share_1", "$type": "Share", "class": "common", "quantity": 1 }, "action": { "$id": "https://api.sb/kilnbakery.com/actions/action_1", "operation": "Share.issue", "status": "done" }, "links": { "self": "https://api.sb/kilnbakery.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const share = await $.Share.issue({ holder: 'holder_1', class: 'Example class', quantity: 1, price: { amount: 9, currency: 'USD' }, agreement: 'agreement_1' }) ``` **CLI** ```bash npx startup-builder do Share.issue --json '{"holder":"holder_1","class":"Example class","quantity":1,"price":{"amount":9,"currency":"USD"},"agreement":"agreement_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Share.issue({ holder: 'holder_1', class: 'Example class', quantity: 1, price: { amount: 9, currency: 'USD' }, agreement: 'agreement_1' })" } } ``` ## Example A [Company](/business/nouns/company) issues 1 million common Shares to a cofounder at $0.0001 each. The record carries the board-approved [Agreement](/business/nouns/agreement) and the book-entry certificate. # issue URL: /business/nouns/share/issue · Id: `verb:Share.issue` · Call: `await $.Share.issue({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Issue records new Shares of one class to a Holder under a board-approved Agreement, with the certificate or book entry. [Issue](/business/nouns/issue) records new [Shares](/business/nouns/share) of one class to a [Holder](/business/nouns/holder) under a board-approved [Agreement](/business/nouns/agreement), with the certificate or book entry. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `holder` | [Holder](/business/nouns/holder) | Yes | The Holder who receives the Shares. | | `class` | `string` | Yes | The share class. | | `quantity` | `integer` | Yes | How many Shares. | | `price` | `money` | Yes | The price paid per Share. | | `agreement` | [Agreement](/business/nouns/agreement) | Yes | The board-approved Agreement that authorizes the issue. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `share` | [Share](/business/nouns/share) | Yes | The issued Share record. | ## Effects - Emits [`Share.issued`](/business/events/Share.issued). - Performed by the [Legal Lead](/agents/legal/legal-lead). - One-way (money): it waits out its delay window, and runs in the `send` and `do` modes. - The cap table reads the new record from its issue date. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Share.issue](/business/nouns/share/issue) | ## When it waits | Gate | Default | | --- | --- | | Decision class | High: one-way, broad (money) | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | 1 business day, in which a watcher can pause, redirect or cancel it; then it runs. | | Limit | The spend [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) or [Mandate](/business/nouns/mandate) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Issue the latest share with a holder and an agreement. ``` **API** ```bash curl -X POST https://api.sb/kilnbakery.com/shares/issue \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"holder":"holder_1","class":"Example class","quantity":1,"price":{"amount":9,"currency":"USD"},"agreement":"agreement_1"}' ``` ```json { "api": "https://api.sb/kilnbakery.com", "share": { "$id": "https://api.sb/kilnbakery.com/shares/share_1", "$type": "Share", "class": "common", "quantity": 1 }, "action": { "$id": "https://api.sb/kilnbakery.com/actions/action_1", "operation": "Share.issue", "status": "done" }, "links": { "self": "https://api.sb/kilnbakery.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const share = await $.Share.issue({ holder: 'holder_1', class: 'Example class', quantity: 1, price: { amount: 9, currency: 'USD' }, agreement: 'agreement_1' }) ``` **CLI** ```bash npx startup-builder do Share.issue --json '{"holder":"holder_1","class":"Example class","quantity":1,"price":{"amount":9,"currency":"USD"},"agreement":"agreement_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Share.issue({ holder: 'holder_1', class: 'Example class', quantity: 1, price: { amount: 9, currency: 'USD' }, agreement: 'agreement_1' })" } } ``` # transfer URL: /business/nouns/share/transfer · Id: `verb:Share.transfer` · Call: `await $.Share.transfer({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Transfer moves Shares from one Holder to another under a signed Agreement, within the Company’s transfer restrictions. Transfer moves [Shares](/business/nouns/share) from one [Holder](/business/nouns/holder) to another under a signed [Agreement](/business/nouns/agreement), within the [Company](/business/nouns/company)’s transfer restrictions. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `share` | [Share](/business/nouns/share) | Yes | The Share record to transfer from. | | `to` | [Holder](/business/nouns/holder) | Yes | The Holder who receives them. | | `quantity` | `integer` | Yes | How many Shares move. | | `agreement` | [Agreement](/business/nouns/agreement) | Yes | The signed transfer Agreement. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `share` | [Share](/business/nouns/share) | Yes | The new Share record held by the receiving Holder. | ## Effects - Emits [`Share.transferred`](/business/events/Share.transferred). - Performed by the [Legal Lead](/agents/legal/legal-lead). - One-way: it waits out its delay window, and runs in the `send` and `do` modes. - Refuses a transfer the bylaws or a right of first refusal block. - Keeps the original record; a transfer writes a pair of records, never an edit. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Share.transfer](/business/nouns/share/transfer) | | A transfer the bylaws or a right of first refusal block | [`refused`](/code/api/errors/refused) | Clear what the check names, then call it again. | [Share.transfer](/business/nouns/share/transfer) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Medium: one-way, bounded | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | 1 business hour, in which a watcher can pause, redirect or cancel it; then it runs. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Transfer the latest share with a holder and an agreement. ``` **API** ```bash curl -X POST https://api.sb/kilnbakery.com/shares/share_1/transfer \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"to":"holder_1","quantity":1,"agreement":"agreement_1"}' ``` ```json { "api": "https://api.sb/kilnbakery.com", "share": { "$id": "https://api.sb/kilnbakery.com/shares/share_1", "$type": "Share", "class": "common", "quantity": 1 }, "action": { "$id": "https://api.sb/kilnbakery.com/actions/action_1", "operation": "Share.transfer", "status": "done" }, "links": { "self": "https://api.sb/kilnbakery.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const share = await $.Share.transfer({ share: 'share_1', to: 'holder_1', quantity: 1, agreement: 'agreement_1' }) ``` **CLI** ```bash npx startup-builder do Share.transfer --json '{"share":"share_1","to":"holder_1","quantity":1,"agreement":"agreement_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Share.transfer({ share: 'share_1', to: 'holder_1', quantity: 1, agreement: 'agreement_1' })" } } ``` # Site URL: /business/nouns/site · Id: `noun:site` > A Site is a website as a Thing: its Pages, navigation, and Brand, served on one or more Domains. A Site is a website as a [Thing](/business/nouns/thing): its [Pages](/business/nouns/page), navigation, and [Brand](/business/nouns/brand), served on one or more [Domains](/business/nouns/domain). ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `navigation` | `json` | No | The menus that link its Pages. |
Inherited from [Interface](/business/nouns/interface): 3 properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `kind` | `string` | Yes | One of `api`, `mcp`, `cli`, `sdk`, `site`, `app`, `docs`, or `webhooks`. | | `path` | `string` | No | Where it is mounted on its Domain, such as `/api`. | | `conformsTo` | `json` | No | The Standards it also speaks, each mapping the Standard’s operations onto the Product’s Verbs. |
## Object ```json { "$id": "https://api.sb/shiftnote.app/sites/site_1", "$type": "Site", "kind": "api", "path": "/", "conformsTo": { "standard": "openai-chat", "operations": { "chat.completions.create": "Listing.write" } }, "navigation": {} } ``` ## Relationships - A Site **contains** many [Pages](/business/nouns/page): a Site serves its [Pages](/business/nouns/page), each at its own path. `contains`, inverse [`containedIn`](/business/nouns/page#rel-contained-in). - A Site **is hosted at** many [Domains](/business/nouns/domain): a Site answers on one or more [Domains](/business/nouns/domain); each Domain serves one Site. `hostedAt`, inverse [`hosts`](/business/nouns/domain#rel-hosts). - A Site **includes** one [Portal](/business/nouns/portal): a Site includes one [Portal](/business/nouns/portal), the signed-in part where each [Customer](/business/nouns/customer) sees only their own records. `includes`, inverse [`includedIn`](/business/nouns/portal#rel-included-in). - A Site **is styled by** one [Brand](/business/nouns/brand): a Site renders one [Brand](/business/nouns/brand)’s name, voice and [Theme](/business/nouns/theme). `styledBy`, inverse [`styles`](/business/nouns/brand#rel-styles). - A Site **has** many [Visits](/business/nouns/visit): each [Visit](/business/nouns/visit) arrives on one Site. `visits`, inverse [`lands`](/business/nouns/visit#rel-lands). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Site.publish](/business/nouns/site/publish) | Publish puts a Site’s current Pages live on its Domains, under its Brand. | [Designer](/agents/product/designer) | [`Site.published`](/business/events/Site.published) | None. | | [Site.create](/business/nouns/site/create) | Creates a Site. Inherited from [Noun](/business/nouns/noun). | None. | `Site.created` | Two-way: `try`, `send`, `do` | | [Site.get](/business/nouns/site/get) | Returns one Site by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Site.list](/business/nouns/site/list) | Returns Sites, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Site.update](/business/nouns/site/update) | Changes the given properties of a Site. Inherited from [Noun](/business/nouns/noun). | None. | `Site.updated` | Two-way: `try`, `send`, `do` | | [Site.delete](/business/nouns/site/delete) | Deletes a Site; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Site.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Site.create` | Yes | Yes | Yes | No | | `Site.get` | Yes | Yes | Yes | Yes | | `Site.list` | Yes | Yes | Yes | Yes | | `Site.update` | Yes | Yes | Yes | No | | `Site.delete` | Yes | Yes | Yes | No | | `Site.publish` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Publish the site “Algebra session”. ``` **API** ```bash curl -X POST https://api.sb/tutorloop.com/sites/site_1/publish \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/tutorloop.com", "site": { "$id": "https://api.sb/tutorloop.com/sites/site_1", "$type": "Site", "kind": "api" }, "action": { "$id": "https://api.sb/tutorloop.com/actions/action_1", "operation": "Site.publish", "status": "done" }, "links": { "self": "https://api.sb/tutorloop.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const site = await $.Site.publish({ site: 'site_1' }) ``` **CLI** ```bash npx startup-builder do Site.publish --json '{"site":"site_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Site.publish({ site: 'site_1' })" } } ``` ## Example A home-inspector directory is a Site with home, city, inspector, and pricing [Pages](/business/nouns/page) under one [Brand](/business/nouns/brand), served on `inspectfinder.com` and `www.inspectfinder.com`. # publish URL: /business/nouns/site/publish · Id: `verb:Site.publish` · Call: `await $.Site.publish({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Publish puts a Site’s current Pages live on its Domains, under its Brand. Publish puts a [Site](/business/nouns/site)’s current [Pages](/business/nouns/page) live on its [Domains](/business/nouns/domain), under its [Brand](/business/nouns/brand). ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `site` | [Site](/business/nouns/site) | Yes | The Site to publish. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `site` | [Site](/business/nouns/site) | Yes | The Site, now live. | ## Effects - Emits [`Site.published`](/business/events/Site.published). - Performed by the [Designer](/agents/product/designer). - Keeps the previous Pages, so a `revert` restores them. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Site.publish](/business/nouns/site/publish) | | The record is not in a state that allows this Verb, so the call is refused. | [`refused`](/code/api/errors/refused) | Read the record, run the Verb that moves it to an allowed state, then retry. | [Site.publish](/business/nouns/site/publish) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Medium: two-way, visible | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | 1 business hour, in which a watcher can pause, redirect or cancel it; then it runs. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Publish the site “Algebra session”. ``` **API** ```bash curl -X POST https://api.sb/tutorloop.com/sites/site_1/publish \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/tutorloop.com", "site": { "$id": "https://api.sb/tutorloop.com/sites/site_1", "$type": "Site", "kind": "api" }, "action": { "$id": "https://api.sb/tutorloop.com/actions/action_1", "operation": "Site.publish", "status": "done" }, "links": { "self": "https://api.sb/tutorloop.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const site = await $.Site.publish({ site: 'site_1' }) ``` **CLI** ```bash npx startup-builder do Site.publish --json '{"site":"site_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Site.publish({ site: 'site_1' })" } } ``` Guides that call it: [Find out if anyone wants this](/start/guides/find-out-if-anyone-wants-this), [Put up a page](/start/guides/put-up-a-page). # Skill URL: /business/nouns/skill · Id: `noun:skill` > A Skill is a capacity a Worker has at a level, such as negotiation or programming, that Roles require. A Skill is a capacity a [Worker](/business/nouns/worker) has at a level, such as negotiation or programming, that [Roles](/business/nouns/role) require. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `level` | `integer` | No | How well the Worker performs it. | ## Object ```json { "$id": "https://api.sb/shiftnote.app/skills/skill_1", "$type": "Skill", "level": 1 } ``` ## Relationships - A Skill **is practiced by** many [Workers](/business/nouns/worker): the Skills a [Worker](/business/nouns/worker) has, each at a level, matched against what [Roles](/business/nouns/role) require. `practicedBy`, inverse [`practices`](/business/nouns/worker#rel-practices). - A Skill **is required by** many [Roles](/business/nouns/role): the Skills, each at a level, a [Worker](/business/nouns/worker) needs to fill the [Role](/business/nouns/role). `requiredBy`, inverse [`requires`](/business/nouns/role#rel-requires). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Skill.create](/business/nouns/skill/create) | Creates a Skill. Inherited from [Noun](/business/nouns/noun). | None. | `Skill.created` | Two-way: `try`, `send`, `do` | | [Skill.get](/business/nouns/skill/get) | Returns one Skill by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Skill.list](/business/nouns/skill/list) | Returns Skills, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Skill.update](/business/nouns/skill/update) | Changes the given properties of a Skill. Inherited from [Noun](/business/nouns/noun). | None. | `Skill.updated` | Two-way: `try`, `send`, `do` | | [Skill.delete](/business/nouns/skill/delete) | Deletes a Skill; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Skill.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Skill.create` | Yes | Yes | Yes | No | | `Skill.get` | Yes | Yes | Yes | Yes | | `Skill.list` | Yes | Yes | Yes | Yes | | `Skill.update` | Yes | Yes | Yes | No | | `Skill.delete` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Add a skill to RouteWise. ``` **API** ```bash curl -X POST https://api.sb/routewise.dev/skills \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"level":1}' ``` ```json { "api": "https://api.sb/routewise.dev", "skill": { "$id": "https://api.sb/routewise.dev/skills/skill_1", "$type": "Skill", "level": 1 }, "action": { "$id": "https://api.sb/routewise.dev/actions/action_1", "operation": "Skill.create", "status": "done" }, "links": { "self": "https://api.sb/routewise.dev/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const skill = await $.Skill.create({ level: 1 }) ``` **CLI** ```bash npx startup-builder do Skill.create --json '{"level":1}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Skill.create({ level: 1 })" } } ``` ## Example The [Sales Lead](/agents/sales/sales-lead) Role requires negotiation at level 3. Sally, the [Agent](/business/nouns/agent) filling it, holds negotiation at level 4. # Software URL: /business/nouns/software · Id: `noun:software` > Software is a Product a Customer uses through Interfaces, from a headless API to a full App. Software is a [Product](/business/nouns/product) a [Customer](/business/nouns/customer) uses through [Interfaces](/business/nouns/interface), from a headless API to a full [App](/business/nouns/app). ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `headless` | `boolean` | No | True when it ships without screens of its own. |
Inherited from [Product](/business/nouns/product): 3 properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `name` | `string` | Yes | The name of the Product. | | `promise` | `text` | Yes | What the Customer can rely on. | | `status` | `string` | Yes | One of `draft`, `selling` or `retired`, set by its Offers. |
## Object ```json { "$id": "https://api.sb/patentpad.com/software/software_1", "$type": "Software", "name": "PatentPad", "promise": "A filing-ready draft within two days.", "status": "draft", "headless": true } ``` ## Relationships - A Software **packages** many [Systems](/business/nouns/system): Software ships [Systems](/business/nouns/system) to its [Customers](/business/nouns/customer) as one [Product](/business/nouns/product), headless or with an [App](/business/nouns/app). `packages`, inverse [`packagedAs`](/business/nouns/system#rel-packaged-as). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Software.create](/business/nouns/software/create) | Creates a Software. Inherited from [Noun](/business/nouns/noun). | None. | `Software.created` | Two-way: `try`, `send`, `do` | | [Software.get](/business/nouns/software/get) | Returns one Software by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Software.list](/business/nouns/software/list) | Returns Software, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Software.update](/business/nouns/software/update) | Changes the given properties of a Software. Inherited from [Noun](/business/nouns/noun). | None. | `Software.updated` | Two-way: `try`, `send`, `do` | | [Software.delete](/business/nouns/software/delete) | Deletes a Software; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Software.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Software.create` | Yes | Yes | Yes | No | | `Software.get` | Yes | Yes | Yes | Yes | | `Software.list` | Yes | Yes | Yes | Yes | | `Software.update` | Yes | Yes | Yes | No | | `Software.delete` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Add a software to ShiftNote. ``` **API** ```bash curl -X POST https://api.sb/shiftnote.app/software \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"name":"ShiftNote","promise":"Every open shift filled 48 hours ahead."}' ``` ```json { "api": "https://api.sb/shiftnote.app", "software": { "$id": "https://api.sb/shiftnote.app/software/software_1", "$type": "Software", "name": "ShiftNote", "promise": "Every open shift filled 48 hours ahead.", "status": "draft" }, "action": { "$id": "https://api.sb/shiftnote.app/actions/action_1", "operation": "Software.create", "status": "done" }, "links": { "self": "https://api.sb/shiftnote.app/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const software = await $.Software.create({ name: 'ShiftNote', promise: 'Every open shift filled 48 hours ahead.' }) ``` **CLI** ```bash npx startup-builder do Software.create --json '{"name":"ShiftNote","promise":"Every open shift filled 48 hours ahead."}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Software.create({ name: 'ShiftNote', promise: 'Every open shift filled 48 hours ahead.' })" } } ``` ## Example An invoicing API is Software. Customers call it headless, and the same Product adds an App for bookkeepers. # Source URL: /business/nouns/source · Id: `noun:source` > A Source is something a Product draws on to keep its promise but did not build: owned, wrapped, or recruited. A Source is something a [Product](/business/nouns/product) draws on to keep its promise but did not build: owned, wrapped, or recruited. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `acquired` | `string` | Yes | One of `owned`, `wrapped`, or `recruited`. | | `terms` | `text` | No | The terms the Startup holds the right to use and resell it under. | ## Object ```json { "$id": "https://api.sb/patentpad.com/sources/source_1", "$type": "Source", "acquired": "owned", "terms": "Resale allowed under the provider’s published API terms; 10,000 calls a month included." } ``` ## Relationships - A Source **has** many [Mappings](/business/nouns/mapping): a Source reaches the registry’s [Nouns](/business/nouns/noun) and [Verbs](/business/nouns/verb) through its [Mappings](/business/nouns/mapping), one per Verb it serves. `mappings`, inverse [`translates`](/business/nouns/mapping#rel-translates). - A Source **supplies** many [Products](/business/nouns/product): a [Product](/business/nouns/product) keeps its promise with Sources it did not build: owned, wrapped, or recruited. `supplies`, inverse [`drawsOn`](/business/nouns/product#rel-draws-on). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Source.create](/business/nouns/source/create) | Creates a Source. Inherited from [Noun](/business/nouns/noun). | None. | `Source.created` | Two-way: `try`, `send`, `do` | | [Source.get](/business/nouns/source/get) | Returns one Source by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Source.list](/business/nouns/source/list) | Returns Sources, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Source.update](/business/nouns/source/update) | Changes the given properties of a Source. Inherited from [Noun](/business/nouns/noun). | None. | `Source.updated` | Two-way: `try`, `send`, `do` | | [Source.delete](/business/nouns/source/delete) | Deletes a Source; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Source.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Source.create` | Yes | Yes | Yes | No | | `Source.get` | Yes | Yes | Yes | Yes | | `Source.list` | Yes | Yes | Yes | Yes | | `Source.update` | Yes | Yes | Yes | No | | `Source.delete` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Add a source to ShiftNote. ``` **API** ```bash curl -X POST https://api.sb/shiftnote.app/sources \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"acquired":"owned"}' ``` ```json { "api": "https://api.sb/shiftnote.app", "source": { "$id": "https://api.sb/shiftnote.app/sources/source_1", "$type": "Source", "acquired": "owned" }, "action": { "$id": "https://api.sb/shiftnote.app/actions/action_1", "operation": "Source.create", "status": "done" }, "links": { "self": "https://api.sb/shiftnote.app/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const source = await $.Source.create({ acquired: 'owned' }) ``` **CLI** ```bash npx startup-builder do Source.create --json '{"acquired":"owned"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Source.create({ acquired: 'owned' })" } } ``` ## Example A [Dataset](/business/nouns/dataset) of business registrations draws on state filings (wrapped), its own entity-matching rules (owned), and corrections from listed firms (recruited). # activate URL: /business/nouns/sso-connection/activate · Id: `verb:SSOConnection.activate` · Call: `await $.SSOConnection.activate({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Activate turns an SSO Connection on after a test sign-in passes, so the Tenant’s people sign in through it. Activate turns an [SSO Connection](/business/nouns/sso-connection) on after a test sign-in passes, so the [Tenant](/business/nouns/tenant)’s people sign in through it. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `connection` | [SSO Connection](/business/nouns/sso-connection) | Yes | The SSO Connection to turn on. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `connection` | [SSO Connection](/business/nouns/sso-connection) | Yes | The SSO Connection, now active. | ## Effects - Emits [`SSOConnection.activated`](/business/events/SSOConnection.activated). - Performed by the [Security Engineer](/agents/engineering/security-engineer). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - A failing connection or a certificate 30 days from expiry emits an Event to the Startup and a notice to the admin. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [SSOConnection.activate](/business/nouns/sso-connection/activate) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Activate the latest SSO connection. ``` **API** ```bash curl -X POST https://api.sb/quietcopy.com/sso-connections/sso_connection_1/activate \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/quietcopy.com", "connection": { "$id": "https://api.sb/quietcopy.com/sso-connections/sso_connection_1", "$type": "SSOConnection", "protocol": "saml", "state": "draft" }, "action": { "$id": "https://api.sb/quietcopy.com/actions/action_1", "operation": "SSOConnection.activate", "status": "done" }, "links": { "self": "https://api.sb/quietcopy.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const connection = await $.SSOConnection.activate({ connection: 'sso_connection_1' }) ``` **CLI** ```bash npx startup-builder do SSOConnection.activate --json '{"connection":"sso_connection_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.SSOConnection.activate({ connection: 'sso_connection_1' })" } } ``` Guides that call it: [Set up SSO for a customer](/products/app/set-up-sso-for-a-customer). # deactivate URL: /business/nouns/sso-connection/deactivate · Id: `verb:SSOConnection.deactivate` · Call: `await $.SSOConnection.deactivate({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Deactivate turns an SSO Connection off, so nobody signs in through it; its configuration is kept. Deactivate turns an [SSO Connection](/business/nouns/sso-connection) off, so nobody signs in through it; its settings are kept. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `connection` | [SSO Connection](/business/nouns/sso-connection) | Yes | The SSO Connection to turn off. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `connection` | [SSO Connection](/business/nouns/sso-connection) | Yes | The SSO Connection, now `inactive`. | ## Effects - Emits [`SSOConnection.deactivated`](/business/events/SSOConnection.deactivated). - Performed by the [Security Engineer](/agents/engineering/security-engineer). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Ends every session that signed in through it. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [SSOConnection.deactivate](/business/nouns/sso-connection/deactivate) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Deactivate the latest SSO connection. ``` **API** ```bash curl -X POST https://api.sb/routewise.dev/sso-connections/sso_connection_1/deactivate \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/routewise.dev", "connection": { "$id": "https://api.sb/routewise.dev/sso-connections/sso_connection_1", "$type": "SSOConnection", "protocol": "saml", "state": "draft" }, "action": { "$id": "https://api.sb/routewise.dev/actions/action_1", "operation": "SSOConnection.deactivate", "status": "done" }, "links": { "self": "https://api.sb/routewise.dev/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const connection = await $.SSOConnection.deactivate({ connection: 'sso_connection_1' }) ``` **CLI** ```bash npx startup-builder do SSOConnection.deactivate --json '{"connection":"sso_connection_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.SSOConnection.deactivate({ connection: 'sso_connection_1' })" } } ``` # SSO Connection URL: /business/nouns/sso-connection · Id: `noun:sso-connection` > An SSO Connection links a Customer’s own identity system to its Tenant, so the Customer’s people sign in through it. An SSO Connection links a [Customer](/business/nouns/customer)’s own identity system to its [Tenant](/business/nouns/tenant), so the Customer’s people sign in through it. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `protocol` | `string` | Yes | How sign-in is asserted: `saml` or `oidc`. | | `state` | `string` | Yes | Where it stands; only `active` signs anyone in. | | `certificateExpiresAt` | `datetime` | No | When the signing certificate expires; the Customer’s admin hears 30 days before. | | `testedAt` | `datetime` | No | When the Customer’s admin last completed a test sign-in. | ## Object ```json { "$id": "https://api.sb/tutorloop.com/sso-connections/sso_connection_1", "$type": "SSOConnection", "protocol": "saml", "state": "draft", "certificateExpiresAt": "2026-10-22T12:00:00Z", "testedAt": "2026-10-22T12:00:00Z" } ``` ## Relationships - A SSO Connection **serves** one [Tenant](/business/nouns/tenant): a [Tenant](/business/nouns/tenant)’s people sign in through its SSO Connections; the [Customer](/business/nouns/customer)’s admin owns each one. `serves`, inverse [`signsInVia`](/business/nouns/tenant#rel-signs-in-via). ## Lifecycle | State | Meaning | Moves to | | --- | --- | --- | | `draft` (first) | Its configuration is entered, and no test sign-in has passed. | `active` by [SSOConnection.activate](/business/nouns/sso-connection/activate) | | `active` | Everyone in the Tenant signs in through it. | `failing` on [`SSOConnection.failed`](/business/nouns/sso-connection#ssoconnectionfailed); `inactive` by [SSOConnection.deactivate](/business/nouns/sso-connection/deactivate) | | `failing` | Sign-ins through it fail, and the Customer’s admin has been told why. | `active` by [SSOConnection.activate](/business/nouns/sso-connection/activate); `inactive` by [SSOConnection.deactivate](/business/nouns/sso-connection/deactivate) | | `inactive` | Turned off: nobody signs in through it, and its configuration is kept. | `active` by [SSOConnection.activate](/business/nouns/sso-connection/activate) | ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [SSOConnection.activate](/business/nouns/sso-connection/activate) | Activate turns an SSO Connection on after a test sign-in passes, so the Tenant’s people sign in through it. | [Security Engineer](/agents/engineering/security-engineer) | [`SSOConnection.activated`](/business/events/SSOConnection.activated) | Two-way: `try`, `send`, `do` | | [SSOConnection.deactivate](/business/nouns/sso-connection/deactivate) | Deactivate turns an SSO Connection off, so nobody signs in through it; its configuration is kept. | [Security Engineer](/agents/engineering/security-engineer) | [`SSOConnection.deactivated`](/business/events/SSOConnection.deactivated) | Two-way: `try`, `send`, `do` | | [SSOConnection.create](/business/nouns/sso-connection/create) | Creates a SSO Connection. Inherited from [Noun](/business/nouns/noun). | None. | `SSOConnection.created` | Two-way: `try`, `send`, `do` | | [SSOConnection.get](/business/nouns/sso-connection/get) | Returns one SSO Connection by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [SSOConnection.list](/business/nouns/sso-connection/list) | Returns SSO Connections, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [SSOConnection.update](/business/nouns/sso-connection/update) | Changes the given properties of a SSO Connection. Inherited from [Noun](/business/nouns/noun). | None. | `SSOConnection.updated` | Two-way: `try`, `send`, `do` | ## Events Events no Verb emits. Each Verb’s Event is in the Verbs table above; every Event is delivered in the same shape. ### SSOConnection.failed Sign-ins through an SSO Connection started failing, from an expired certificate or a change on the Customer’s side. Raised by the rail. | Field | Type | Required | Description | | --- | --- | --- | --- | | `name` | `string` | Yes | `SSOConnection.failed`. | | `at` | `datetime` | Yes | When it happened. | | `seq` | `integer` | No | Its position in the namespace, one more than the Event before; any seq is a cursor into the history. | | `data` | `json` | Yes | The Thing as the Action left it. | | `data.ssoConnection` | [SSO Connection](/business/nouns/sso-connection) | Yes | The SSO Connection as the change left it. | | `data.ssoConnection.protocol` | `string` | Yes | How sign-in is asserted: `saml` or `oidc`. | | `data.ssoConnection.state` | `string` | Yes | Where it stands; only `active` signs anyone in. | | `data.ssoConnection.certificateExpiresAt` | `datetime` | No | When the signing certificate expires; the Customer’s admin hears 30 days before. | | `data.ssoConnection.testedAt` | `datetime` | No | When the Customer’s admin last completed a test sign-in. | | `data.cause` | `string` | Yes | What failed: `certificateExpired`, `signatureInvalid`, or `providerUnreachable`. | | `data.previous.state` | `string` | Yes | The `state` before this Event: `active`. | ```json { "$id": "https://api.sb/tutorloop.com/events/event_1", "$type": "Event", "name": "SSOConnection.failed", "at": "2026-10-22T12:00:00Z", "data": { "ssoConnection": { "$id": "https://api.sb/tutorloop.com/sso-connections/sso_connection_1", "$type": "SSOConnection", "protocol": "saml", "state": "failing", "certificateExpiresAt": "2026-10-22T12:00:00Z", "testedAt": "2026-10-22T12:00:00Z" }, "cause": "certificateExpired", "previous": { "state": "active" } }, "seq": 1 } ``` ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `SSOConnection.create` | Yes | Yes | No | No | | `SSOConnection.get` | Yes | Yes | Yes | Yes | | `SSOConnection.list` | Yes | Yes | Yes | Yes | | `SSOConnection.update` | Yes | Yes | No | No | | `SSOConnection.activate` | Yes | Yes | No | No | | `SSOConnection.deactivate` | Yes | Yes | No | No | ## Call it **Ask** ```text Activate the latest SSO connection. ``` **API** ```bash curl -X POST https://api.sb/quietcopy.com/sso-connections/sso_connection_1/activate \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/quietcopy.com", "connection": { "$id": "https://api.sb/quietcopy.com/sso-connections/sso_connection_1", "$type": "SSOConnection", "protocol": "saml", "state": "draft" }, "action": { "$id": "https://api.sb/quietcopy.com/actions/action_1", "operation": "SSOConnection.activate", "status": "done" }, "links": { "self": "https://api.sb/quietcopy.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const connection = await $.SSOConnection.activate({ connection: 'sso_connection_1' }) ``` **CLI** ```bash npx startup-builder do SSOConnection.activate --json '{"connection":"sso_connection_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.SSOConnection.activate({ connection: 'sso_connection_1' })" } } ``` ## Example A 2,000-person [Customer](/business/nouns/customer) connects its identity system to its [Tenant](/business/nouns/tenant) over `saml`. Its admin completes a test sign-in, the connection goes `active`, and passwords stop working for that domain. # Standard URL: /business/nouns/standard · Id: `noun:standard` > A Standard is a spec an Interface conforms to, so a Startup may publish its Product’s Verbs in a shape outside callers already use. A Standard is a spec an [Interface](/business/nouns/interface) conforms to, so a [Startup](/business/nouns/startup) may publish its [Product](/business/nouns/product)’s [Verbs](/business/nouns/verb) in a shape outside callers already use. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `spec` | `url` | Yes | The published specification its translator implements. | | `path` | `string` | Yes | Where its translator answers on an Interface, such as `/scim/v2` or `/v1/chat/completions`. | | `operations` | `string[]` | Yes | The operations its translator accepts; a Startup maps each one onto one of its own Verbs. | ## Object ```json { "$id": "https://api.sb/patentpad.com/standards/standard_1", "$type": "Standard", "spec": "https://patentpad.com", "path": "/", "operations": [ "chat.completions.create" ] } ``` ## Relationships - A Standard **spoken by** many [Interfaces](/business/nouns/interface): Callers in a Standard’s shape reach the [Interface](/business/nouns/interface)’s [Verbs](/business/nouns/verb) through the platform’s one translator for that Standard. `spokenBy`, inverse [`speaks`](/business/nouns/interface#rel-speaks). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Standard.get](/business/nouns/standard/get) | Returns one Standard by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Standard.list](/business/nouns/standard/list) | Returns Standards, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | A Standard is kept forever and never edited: it has no `update` or `delete`. ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Standard.get` | Yes | Yes | Yes | Yes | | `Standard.list` | Yes | Yes | Yes | Yes | ## Call it **Ask** ```text Show me the latest standard. ``` **API** ```bash curl https://api.sb/shiftnote.app/standards/standard_1 \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/shiftnote.app", "$type": "Standard", "$id": "https://api.sb/shiftnote.app/standards/standard_1", "standard": { "$id": "https://api.sb/shiftnote.app/standards/standard_1", "$type": "Standard", "spec": "https://shiftnote.app", "path": "/", "operations": [ "chat.completions.create" ] }, "links": { "self": "https://api.sb/shiftnote.app/standards/standard_1", "up": "https://api.sb/shiftnote.app/standards" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const standard = await $.Standard.get({ id: 'standard_1' }) ``` **CLI** ```bash npx startup-builder do Standard.get --json '{"id":"standard_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Standard.get({ id: 'standard_1' })" } } ``` ## Example `listsmith.ai` maps the `openai-chat` Standard's `chat.completions.create` operation onto its own `Listing.write` Verb. A [Customer](/business/nouns/customer)'s existing model client then calls `https://api.listsmith.ai/v1/chat/completions` and gets a listing back in the shape it expects. # extend URL: /business/nouns/startup-template/extend · Id: `verb:StartupTemplate.extend` · Call: `await $.StartupTemplate.extend({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Extend adds a Startup Template to a Startup’s bases, pinned to a Version, so the Startup inherits its definition. Extend adds a [Startup Template](/business/nouns/startup-template) to a [Startup](/business/nouns/startup)’s bases, pinned to a [Version](/business/nouns/version), so the Startup inherits its definition. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `startupTemplate` | [Startup Template](/business/nouns/startup-template) | Yes | The Startup Template to inherit. | | `startup` | [Startup](/business/nouns/startup) | Yes | The Startup that extends it. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `startup` | [Startup](/business/nouns/startup) | Yes | The Startup, with the Startup Template among its bases. | | `startupTemplate` | [Startup Template](/business/nouns/startup-template) | Yes | The Startup Template extended. | ## Effects - Emits [`StartupTemplate.extended`](/business/events/StartupTemplate.extended). - Performed by the [Founder](/agents/founding/founder). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Pins the Startup Template’s current Version in the Startup’s lockfile. - Refuses a clash between two bases until the Startup settles it. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [StartupTemplate.extend](/business/nouns/startup-template/extend) | | A clash between two bases until the Startup settles it | [`refused`](/code/api/errors/refused) | Clear what the check names, then call it again. | [StartupTemplate.extend](/business/nouns/startup-template/extend) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Extend the latest startup template with a startup. ``` **API** ```bash curl -X POST https://api.sb/ledgerlark.com/startup-templates/startup_template_1/extend \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"startup":"startup_1"}' ``` ```json { "api": "https://api.sb/ledgerlark.com", "startup": { "$id": "https://api.sb/ledgerlark.com/startups/startup_1", "$type": "Startup", "name": "LedgerLark" }, "startupTemplate": { "$id": "https://api.sb/ledgerlark.com/startup-templates/startup_template_1", "$type": "StartupTemplate", "slug": "ledger-lark", "operatingModel": "autonomous", "motions": [ "Example motions" ] }, "action": { "$id": "https://api.sb/ledgerlark.com/actions/action_1", "operation": "StartupTemplate.extend", "status": "done" }, "links": { "self": "https://api.sb/ledgerlark.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { startup, startupTemplate } = await $.StartupTemplate.extend({ startupTemplate: 'startup_template_1', startup: 'startup_1' }) ``` **CLI** ```bash npx startup-builder do StartupTemplate.extend --json '{"startupTemplate":"startup_template_1","startup":"startup_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.StartupTemplate.extend({ startupTemplate: 'startup_template_1', startup: 'startup_1' })" } } ``` # Startup Template URL: /business/nouns/startup-template · Id: `noun:startup-template` > A Startup Template is an operating model, one or more Product Templates, and the Motions they sell through, which a new Startup starts from. A Startup Template is an operating model, one or more [Product Templates](/business/nouns/product-template), and the [Motions](/business/nouns/motion) they sell through, which a new [Startup](/business/nouns/startup) starts from. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `slug` | `string` | Yes | The argument to `create --template` and the page path under `/start/templates`. | | `operatingModel` | `string` | Yes | The human and Agent mix: `autonomous`, `single-human`, or `multi-human`. | | `motions` | `string[]` | Yes | The Motions its Offers sell through, such as `b2b` or `b2a`. | | `extends` | [Startup Template](/business/nouns/startup-template) | No | The base Startup Template whose Product Templates, Systems, Processes, and Roles it inherits. | ## Object ```json { "$id": "https://api.sb/tutorloop.com/startup-templates/startup_template_1", "$type": "StartupTemplate", "slug": "tutor-loop", "operatingModel": "autonomous", "motions": [ "Example motions" ], "extends": "startup_template_1" } ``` ## Relationships - A Startup Template **combines** many [Product Templates](/business/nouns/product-template): a Startup Template combines one or more [Product Templates](/business/nouns/product-template), each one kind of [Product](/business/nouns/product) its [Startups](/business/nouns/startup) sell. `combines`, inverse [`combinedIn`](/business/nouns/product-template#rel-combined-in). - A Startup Template **is extended by** many [Startup Templates](/business/nouns/startup-template): a Startup Template inherits its base’s [Product Templates](/business/nouns/product-template), [Systems](/business/nouns/system), [Processes](/business/nouns/process) and [Roles](/business/nouns/role), and overrides what differs. `extendedBy`, inverse `extends`. - A Startup Template **extends** one [Startup Template](/business/nouns/startup-template): a Startup Template inherits its base’s [Product Templates](/business/nouns/product-template), [Systems](/business/nouns/system), [Processes](/business/nouns/process) and [Roles](/business/nouns/role), and overrides what differs. `extends`, inverse `extendedBy`. - A Startup Template **sells through** many [Motions](/business/nouns/motion): a Startup Template names the [Motions](/business/nouns/motion) its [Startups](/business/nouns/startup) sell through, such as b2b or b2a. `sellsThrough`, inverse [`soldThroughBy`](/business/nouns/motion#rel-sold-through-by). - A Startup Template **has** many [Startups](/business/nouns/startup): a [Startup](/business/nouns/startup) inherits a Startup Template’s definition, pinned to a [Version](/business/nouns/version) it upgrades through a [Change](/business/nouns/change). `startups`, inverse [`extends`](/business/nouns/startup#rel-extends). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [StartupTemplate.extend](/business/nouns/startup-template/extend) | Extend adds a Startup Template to a Startup’s bases, pinned to a Version, so the Startup inherits its definition. | [Founder](/agents/founding/founder) | [`StartupTemplate.extended`](/business/events/StartupTemplate.extended) | Two-way: `try`, `send`, `do` | | [StartupTemplate.promote](/business/nouns/startup-template/promote) | Promote moves one Startup’s refinement into a Startup Template, so every Startup that extends it inherits the refinement. | [Product Lead](/agents/product/product-lead) | [`StartupTemplate.promoted`](/business/events/StartupTemplate.promoted) | Two-way: `try`, `send`, `do` | | [StartupTemplate.upgrade](/business/nouns/startup-template/upgrade) | Upgrade moves a Startup to a newer Version of a Startup Template it extends, through a Change it can review. | [Engineering Lead](/agents/engineering/engineering-lead) | [`StartupTemplate.upgraded`](/business/events/StartupTemplate.upgraded) | Two-way: `try`, `send`, `do` | | [StartupTemplate.create](/business/nouns/startup-template/create) | Creates a Startup Template. Inherited from [Noun](/business/nouns/noun). | None. | `StartupTemplate.created` | Two-way: `try`, `send`, `do` | | [StartupTemplate.get](/business/nouns/startup-template/get) | Returns one Startup Template by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [StartupTemplate.list](/business/nouns/startup-template/list) | Returns Startup Templates, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [StartupTemplate.update](/business/nouns/startup-template/update) | Changes the given properties of a Startup Template. Inherited from [Noun](/business/nouns/noun). | None. | `StartupTemplate.updated` | Two-way: `try`, `send`, `do` | | [StartupTemplate.delete](/business/nouns/startup-template/delete) | Deletes a Startup Template; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `StartupTemplate.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `StartupTemplate.create` | Yes | Yes | Yes | No | | `StartupTemplate.get` | Yes | Yes | Yes | Yes | | `StartupTemplate.list` | Yes | Yes | Yes | Yes | | `StartupTemplate.update` | Yes | Yes | Yes | No | | `StartupTemplate.delete` | Yes | Yes | Yes | No | | `StartupTemplate.extend` | Yes | Yes | Yes | No | | `StartupTemplate.promote` | Yes | Yes | Yes | No | | `StartupTemplate.upgrade` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Extend the latest startup template with a startup. ``` **API** ```bash curl -X POST https://api.sb/ledgerlark.com/startup-templates/startup_template_1/extend \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"startup":"startup_1"}' ``` ```json { "api": "https://api.sb/ledgerlark.com", "startup": { "$id": "https://api.sb/ledgerlark.com/startups/startup_1", "$type": "Startup", "name": "LedgerLark" }, "startupTemplate": { "$id": "https://api.sb/ledgerlark.com/startup-templates/startup_template_1", "$type": "StartupTemplate", "slug": "ledger-lark", "operatingModel": "autonomous", "motions": [ "Example motions" ] }, "action": { "$id": "https://api.sb/ledgerlark.com/actions/action_1", "operation": "StartupTemplate.extend", "status": "done" }, "links": { "self": "https://api.sb/ledgerlark.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { startup, startupTemplate } = await $.StartupTemplate.extend({ startupTemplate: 'startup_template_1', startup: 'startup_1' }) ``` **CLI** ```bash npx startup-builder do StartupTemplate.extend --json '{"startupTemplate":"startup_template_1","startup":"startup_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.StartupTemplate.extend({ startupTemplate: 'startup_template_1', startup: 'startup_1' })" } } ``` ## Example The `autonomous-data-api` Startup Template starts a permit-status API with the [Dataset API](/products/templates/dataset-api) Product Template, usage pricing and its default [Roles](/business/nouns/role) awake. The founder fills in the founding [Hypothesis](/business/nouns/hypothesis), and the rest is inherited. # promote URL: /business/nouns/startup-template/promote · Id: `verb:StartupTemplate.promote` · Call: `await $.StartupTemplate.promote({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Promote moves one Startup’s refinement into a Startup Template, so every Startup that extends it inherits the refinement. Promote moves one [Startup](/business/nouns/startup)’s refinement into a [Startup Template](/business/nouns/startup-template), so every Startup that extends it inherits the refinement. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `startupTemplate` | [Startup Template](/business/nouns/startup-template) | Yes | The Startup Template that receives the refinement. | | `startup` | [Startup](/business/nouns/startup) | Yes | The Startup that holds the refinement. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `change` | [Change](/business/nouns/change) | Yes | The Change against the Startup Template. | | `startupTemplate` | [Startup Template](/business/nouns/startup-template) | Yes | The Startup Template that received the refinement. | ## Effects - Emits [`StartupTemplate.promoted`](/business/events/StartupTemplate.promoted). - Performed by the [Product Lead](/agents/product/product-lead). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Opens a Change against the Startup Template. - Reaches each extending Startup as an `upgrade`. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [StartupTemplate.promote](/business/nouns/startup-template/promote) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Promote the latest startup template with a startup. ``` **API** ```bash curl -X POST https://api.sb/ledgerlark.com/startup-templates/startup_template_1/promote \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"startup":"startup_1"}' ``` ```json { "api": "https://api.sb/ledgerlark.com", "change": { "$id": "https://api.sb/ledgerlark.com/changes/change_1", "$type": "Change", "status": "Open", "base": "version_1" }, "startupTemplate": { "$id": "https://api.sb/ledgerlark.com/startup-templates/startup_template_1", "$type": "StartupTemplate", "slug": "ledger-lark", "operatingModel": "autonomous", "motions": [ "Example motions" ] }, "action": { "$id": "https://api.sb/ledgerlark.com/actions/action_1", "operation": "StartupTemplate.promote", "status": "done" }, "links": { "self": "https://api.sb/ledgerlark.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { change, startupTemplate } = await $.StartupTemplate.promote({ startupTemplate: 'startup_template_1', startup: 'startup_1' }) ``` **CLI** ```bash npx startup-builder do StartupTemplate.promote --json '{"startupTemplate":"startup_template_1","startup":"startup_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.StartupTemplate.promote({ startupTemplate: 'startup_template_1', startup: 'startup_1' })" } } ``` # upgrade URL: /business/nouns/startup-template/upgrade · Id: `verb:StartupTemplate.upgrade` · Call: `await $.StartupTemplate.upgrade({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Upgrade moves a Startup to a newer Version of a Startup Template it extends, through a Change it can review. Upgrade moves a [Startup](/business/nouns/startup) to a newer [Version](/business/nouns/version) of a [Startup Template](/business/nouns/startup-template) it extends, through a [Change](/business/nouns/change) it can review. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `startupTemplate` | [Startup Template](/business/nouns/startup-template) | Yes | The Startup Template to upgrade. | | `startup` | [Startup](/business/nouns/startup) | Yes | The Startup that extends it. | | `version` | [Version](/business/nouns/version) | No | The target Version; the latest when absent. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `change` | [Change](/business/nouns/change) | Yes | The Change that moves the pin, with its three-way diff. | | `startupTemplate` | [Startup Template](/business/nouns/startup-template) | Yes | The Startup Template upgraded to. | ## Effects - Emits [`StartupTemplate.upgraded`](/business/events/StartupTemplate.upgraded). - Performed by the [Engineering Lead](/agents/engineering/engineering-lead). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Opens a Change; nothing moves until it merges. - Names each dependency the Change moves, from which Version to which. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [StartupTemplate.upgrade](/business/nouns/startup-template/upgrade) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Upgrade the latest startup template with a startup. ``` **API** ```bash curl -X POST https://api.sb/shiftnote.app/startup-templates/startup_template_1/upgrade \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"startup":"startup_1"}' ``` ```json { "api": "https://api.sb/shiftnote.app", "change": { "$id": "https://api.sb/shiftnote.app/changes/change_1", "$type": "Change", "status": "Open", "base": "version_1" }, "startupTemplate": { "$id": "https://api.sb/shiftnote.app/startup-templates/startup_template_1", "$type": "StartupTemplate", "slug": "shift-note", "operatingModel": "autonomous", "motions": [ "Example motions" ] }, "action": { "$id": "https://api.sb/shiftnote.app/actions/action_1", "operation": "StartupTemplate.upgrade", "status": "done" }, "links": { "self": "https://api.sb/shiftnote.app/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { change, startupTemplate } = await $.StartupTemplate.upgrade({ startupTemplate: 'startup_template_1', startup: 'startup_1' }) ``` **CLI** ```bash npx startup-builder do StartupTemplate.upgrade --json '{"startupTemplate":"startup_template_1","startup":"startup_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.StartupTemplate.upgrade({ startupTemplate: 'startup_template_1', startup: 'startup_1' })" } } ``` # advance URL: /business/nouns/startup/advance · Id: `verb:Startup.advance` · Call: `await $.Startup.advance({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Advance moves a Startup to its next Lifecycle state once every entry check of that state passes. Advance moves a [Startup](/business/nouns/startup) to its next [Lifecycle](/business/nouns/lifecycle) state once every entry check of that state passes. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `startup` | [Startup](/business/nouns/startup) | Yes | The Startup to advance. | | `to` | `string` | No | The target state. Defaults to the next state. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `startup` | [Startup](/business/nouns/startup) | Yes | The Startup in its new state. | ## Effects - Emits [`Startup.advanced`](/business/events/Startup.advanced). - Runs the entry checks of the target state, in order. - Refuses the Action and names each failing check when any check fails. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | Any entry check of the target [Lifecycle](/business/nouns/lifecycle) state | [`refused`](/code/api/errors/refused) | Pass each check the error names. | [Startup.advance](/business/nouns/startup/advance) | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Startup.advance](/business/nouns/startup/advance) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Advance ShiftNote. ``` **API** ```bash curl -X POST https://api.sb/shiftnote.app/startups/startup_1/advance \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/shiftnote.app", "startup": { "$id": "https://api.sb/shiftnote.app/startups/startup_1", "$type": "Startup", "name": "ShiftNote" }, "action": { "$id": "https://api.sb/shiftnote.app/actions/action_1", "operation": "Startup.advance", "status": "done" }, "links": { "self": "https://api.sb/shiftnote.app/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const startup = await $.Startup.advance({ startup: 'startup_1' }) ``` **CLI** ```bash npx startup-builder do Startup.advance --json '{"startup":"startup_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Startup.advance({ startup: 'startup_1' })" } } ``` # build URL: /business/nouns/startup/build · Id: `verb:Startup.build` · Call: `await $.Startup.build({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Build provisions the Systems, Sites and Interfaces a Startup’s definition declares, and moves the Startup to Building. Build provisions the [Systems](/business/nouns/system), [Sites](/business/nouns/site) and [Interfaces](/business/nouns/interface) a [Startup](/business/nouns/startup)’s definition declares, and moves the Startup to Building. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `startup` | [Startup](/business/nouns/startup) | Yes | The Startup to build. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `startup` | [Startup](/business/nouns/startup) | Yes | The Startup, now Building. | ## Effects - Emits [`Startup.built`](/business/events/Startup.built). - Performed by the [Engineering Lead](/agents/engineering/engineering-lead). - Provisions every System the Startup’s Templates include. - Moves the Startup from Idea to Building. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | Template chosen (`building-template`) | [`refused`](/code/api/errors/refused) | Name a Startup Template in the definition. | [Startup.update](/business/nouns/startup/update) | | Problem stated (`building-problem`) | [`refused`](/code/api/errors/refused) | Write the problem slot with its workarounds and why now. | [Hypothesis.create](/business/nouns/hypothesis/create) | | Brand named (`building-brand`) | [`refused`](/code/api/errors/refused) | Give the Brand a name, a voice, a logo, and a theme. | [Brand.update](/business/nouns/brand/update) | | Products declared (`building-products`) | [`refused`](/code/api/errors/refused) | Set the kind of every Product. | [Product.update](/business/nouns/product/update) | | Three slots at Commitment (`building-slots`) | [`refused`](/code/api/errors/refused) | Run the cheapest test on each slot below Commitment, such as a reserve deposit. | [Experiment.start](/business/nouns/experiment/start) | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Startup.build](/business/nouns/startup/build) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Build RouteWise. ``` **API** ```bash curl -X POST https://api.sb/routewise.dev/startups/startup_1/build \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/routewise.dev", "startup": { "$id": "https://api.sb/routewise.dev/startups/startup_1", "$type": "Startup", "name": "RouteWise" }, "action": { "$id": "https://api.sb/routewise.dev/actions/action_1", "operation": "Startup.build", "status": "done" }, "links": { "self": "https://api.sb/routewise.dev/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const startup = await $.Startup.build({ startup: 'startup_1' }) ``` **CLI** ```bash npx startup-builder do Startup.build --json '{"startup":"startup_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Startup.build({ startup: 'startup_1' })" } } ``` Guides that call it: [Start a business](/business/start-a-business), [Turn my app into a business](/start/guides/turn-my-app-into-a-business). # claim URL: /business/nouns/startup/claim · Id: `verb:Startup.claim` · Call: `await $.Startup.claim({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Claim binds a provisional Startup to a verified owner, which enables payments and every Verb that moves money. Claim binds a provisional [Startup](/business/nouns/startup) to a verified owner, which enables payments and every [Verb](/business/nouns/verb) that moves money. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `startup` | [Startup](/business/nouns/startup) | Yes | The provisional Startup. | | `claimToken` | `string` | Yes | The token issued when the Startup was created. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `startup` | [Startup](/business/nouns/startup) | Yes | The Startup, now owned. | ## Effects - Emits [`Startup.claimed`](/business/events/Startup.claimed). - Opens the Startup’s payment account. - Lifts the no-money Limit that holds on every provisional Startup. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The input does not match the schema of the operation. | [`invalid-input`](/code/api/errors/invalid-input) | Read the schema of the operation, then send every required field with the right type. | [Startup.claim](/business/nouns/startup/claim) | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Startup.claim](/business/nouns/startup/claim) | | The record is not in a state that allows this Verb, so the call is refused. | [`refused`](/code/api/errors/refused) | Read the record, run the Verb that moves it to an allowed state, then retry. | [Startup.claim](/business/nouns/startup/claim) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Claim PatentPad. ``` **API** ```bash curl -X POST https://api.sb/patentpad.com/startups/startup_1/claim \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"claimToken":"Example claim token"}' ``` ```json { "api": "https://api.sb/patentpad.com", "startup": { "$id": "https://api.sb/patentpad.com/startups/startup_1", "$type": "Startup", "name": "PatentPad" }, "action": { "$id": "https://api.sb/patentpad.com/actions/action_1", "operation": "Startup.claim", "status": "done" }, "links": { "self": "https://api.sb/patentpad.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const startup = await $.Startup.claim({ startup: 'startup_1', claimToken: 'Example claim token' }) ``` **CLI** ```bash npx startup-builder do Startup.claim --json '{"startup":"startup_1","claimToken":"Example claim token"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Startup.claim({ startup: 'startup_1', claimToken: 'Example claim token' })" } } ``` Guides that call it: [Open a bank account](/systems/finance/open-a-bank-account). # clone URL: /business/nouns/startup/clone · Id: `verb:Startup.clone` · Call: `await $.Startup.clone({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Clone copies a Startup’s definition into a new Startup once, with no link back to the source. Clone copies a [Startup](/business/nouns/startup)’s definition into a new Startup once, with no link back to the source. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `startup` | [Startup](/business/nouns/startup) | Yes | The Startup to copy. | | `name` | `string` | Yes | The new Startup’s name. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `clone` | [Startup](/business/nouns/startup) | Yes | The new Startup, in Idea. | ## Effects - Emits [`Startup.cloned`](/business/events/Startup.cloned). - Copies definitions, never records: the new Startup starts with no Customers. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The input does not match the schema of the operation. | [`invalid-input`](/code/api/errors/invalid-input) | Read the schema of the operation, then send every required field with the right type. | [Startup.clone](/business/nouns/startup/clone) | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Startup.clone](/business/nouns/startup/clone) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Clone Kiln Bakery. ``` **API** ```bash curl -X POST https://api.sb/kilnbakery.com/startups/startup_1/clone \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"name":"Kiln Bakery"}' ``` ```json { "api": "https://api.sb/kilnbakery.com", "clone": { "$id": "https://api.sb/kilnbakery.com/startups/startup_1", "$type": "Startup", "name": "Kiln Bakery" }, "action": { "$id": "https://api.sb/kilnbakery.com/actions/action_1", "operation": "Startup.clone", "status": "done" }, "links": { "self": "https://api.sb/kilnbakery.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const clone = await $.Startup.clone({ startup: 'startup_1', name: 'Kiln Bakery' }) ``` **CLI** ```bash npx startup-builder do Startup.clone --json '{"startup":"startup_1","name":"Kiln Bakery"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Startup.clone({ startup: 'startup_1', name: 'Kiln Bakery' })" } } ``` # graduate URL: /business/nouns/startup/graduate · Id: `verb:Startup.graduate` · Call: `await $.Startup.graduate({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Graduate moves a Startup to a Company of its own, with its Customers, Domains and records intact. Graduate moves a [Startup](/business/nouns/startup) to a [Company](/business/nouns/company) of its own, with its [Customers](/business/nouns/customer), [Domains](/business/nouns/domain) and records intact. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `startup` | [Startup](/business/nouns/startup) | Yes | The Startup to graduate. | | `company` | [Company](/business/nouns/company) | Yes | The Company that holds it next. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `startup` | [Startup](/business/nouns/startup) | Yes | The Startup, held by its new Company. | ## Effects - Emits [`Startup.graduated`](/business/events/Startup.graduated). - Performed by the [Founder](/agents/founding/founder). - One-way (money, customer): it waits out its delay window, and runs in the `send` and `do` modes. - Changes the Company that holds the Startup. - Keeps its address, Customers and Subscriptions. - Requires a human signature, because it moves equity. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | Company of its own (`graduate-company`) | [`refused`](/code/api/errors/refused) | A company of its own holds the Startup, with its Brand, Customers, and records moved intact. | None. | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Startup.graduate](/business/nouns/startup/graduate) | ## When it waits | Gate | Default | | --- | --- | | Decision class | High: one-way, broad (money, customer) | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | 1 business day, in which a watcher can pause, redirect or cancel it; then it runs. | | Limit | The spend [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) or [Mandate](/business/nouns/mandate) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Graduate Kiln Bakery with a company. ``` **API** ```bash curl -X POST https://api.sb/kilnbakery.com/startups/startup_1/graduate \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"company":"company_1"}' ``` ```json { "api": "https://api.sb/kilnbakery.com", "startup": { "$id": "https://api.sb/kilnbakery.com/startups/startup_1", "$type": "Startup", "name": "Kiln Bakery" }, "action": { "$id": "https://api.sb/kilnbakery.com/actions/action_1", "operation": "Startup.graduate", "status": "done" }, "links": { "self": "https://api.sb/kilnbakery.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const startup = await $.Startup.graduate({ startup: 'startup_1', company: 'company_1' }) ``` **CLI** ```bash npx startup-builder do Startup.graduate --json '{"startup":"startup_1","company":"company_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Startup.graduate({ startup: 'startup_1', company: 'company_1' })" } } ``` # hold URL: /business/nouns/startup/hold · Id: `verb:Startup.hold` · Call: `await $.Startup.hold({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Hold keeps a Startup running in its current Lifecycle state with no new investment from the Studio. Hold keeps a [Startup](/business/nouns/startup) running in its current [Lifecycle](/business/nouns/lifecycle) state with no new investment from the [Studio](/business/nouns/studio). ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `startup` | [Startup](/business/nouns/startup) | Yes | The Startup to hold. | | `reason` | `text` | No | Why the Studio holds it. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `startup` | [Startup](/business/nouns/startup) | Yes | The Startup, now on Hold. | ## Effects - Emits [`Startup.held`](/business/events/Startup.held). - Performed by the [Strategist](/agents/founding/strategist). - Stops new spend from the Studio; the Startup’s own revenue still funds it. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Startup.hold](/business/nouns/startup/hold) | | The record is not in a state that allows this Verb, so the call is refused. | [`refused`](/code/api/errors/refused) | Read the record, run the Verb that moves it to an allowed state, then retry. | [Startup.hold](/business/nouns/startup/hold) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Hold Kiln Bakery. ``` **API** ```bash curl -X POST https://api.sb/kilnbakery.com/startups/startup_1/hold \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/kilnbakery.com", "startup": { "$id": "https://api.sb/kilnbakery.com/startups/startup_1", "$type": "Startup", "name": "Kiln Bakery" }, "action": { "$id": "https://api.sb/kilnbakery.com/actions/action_1", "operation": "Startup.hold", "status": "done" }, "links": { "self": "https://api.sb/kilnbakery.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const startup = await $.Startup.hold({ startup: 'startup_1' }) ``` **CLI** ```bash npx startup-builder do Startup.hold --json '{"startup":"startup_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Startup.hold({ startup: 'startup_1' })" } } ``` # import URL: /business/nouns/startup/import · Id: `verb:Startup.import` · Call: `await $.Startup.import({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Import builds a new Startup from an existing business’s definition: its Offers, Pages, Nouns and Processes. Import builds a new [Startup](/business/nouns/startup) from an existing business’s definition: its [Offers](/business/nouns/offer), [Pages](/business/nouns/page), [Nouns](/business/nouns/noun) and [Processes](/business/nouns/process). ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `source` | `url` | Yes | The existing business’s site or export. | | `template` | [Template](/business/nouns/template) | No | The Template to map the definition onto. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `startup` | [Startup](/business/nouns/startup) | Yes | The new Startup, in Idea. | ## Effects - Emits [`Startup.imported`](/business/events/Startup.imported). - Performed by the [Integration Engineer](/agents/engineering/integration-engineer). - Leaves the source business unchanged. - Marks every imported fact with its source. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The input does not match the schema of the operation. | [`invalid-input`](/code/api/errors/invalid-input) | Read the schema of the operation, then send every required field with the right type. | [Startup.import](/business/nouns/startup/import) | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Startup.import](/business/nouns/startup/import) | | The record is not in a state that allows this Verb, so the call is refused. | [`refused`](/code/api/errors/refused) | Read the record, run the Verb that moves it to an allowed state, then retry. | [Startup.import](/business/nouns/startup/import) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Import Kiln Bakery. ``` **API** ```bash curl -X POST https://api.sb/kilnbakery.com/startups/import \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"source":"https://kilnbakery.com"}' ``` ```json { "api": "https://api.sb/kilnbakery.com", "startup": { "$id": "https://api.sb/kilnbakery.com/startups/startup_1", "$type": "Startup", "name": "Kiln Bakery" }, "action": { "$id": "https://api.sb/kilnbakery.com/actions/action_1", "operation": "Startup.import", "status": "done" }, "links": { "self": "https://api.sb/kilnbakery.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const startup = await $.Startup.import({ source: 'https://kilnbakery.com' }) ``` **CLI** ```bash npx startup-builder do Startup.import --json '{"source":"https://kilnbakery.com"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Startup.import({ source: 'https://kilnbakery.com' })" } } ``` Next: [`Startup.build`](/business/nouns/startup/build) (in `guide:turn-my-app-into-a-business`). Guides that call it: [Turn my app into a business](/start/guides/turn-my-app-into-a-business). # Startup URL: /business/nouns/startup · Id: `noun:startup` > A Startup is the smallest business that can be moved, promoted, or sold on its own, with its own Products, Offers, Customers, and P&L. A Startup is the smallest business that can be moved, promoted, or sold on its own, with its own [Products](/business/nouns/product), [Offers](/business/nouns/offer), [Customers](/business/nouns/customer), and P&L. A [Studio](/business/nouns/studio) builds it; a [Company](/business/nouns/company) holds it. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `name` | `string` | Yes | The name the Startup trades under. | | `domain` | `url` | No | The canonical hostname of the Startup. | | `launchedAt` | `datetime` | No | When the Startup went live. | | `template` | `string` | No | The slug of the template it extends; the root one when none is named. | | `idea` | `text` | No | The Idea it starts from, in a sentence, recorded as its Idea. | | `spendState` | `string` | No | How freely money Limits allow spend: `free`, `tight` (discretionary Limits halved) or `hold` (one-way spend stops). | ## Object ```json { "$id": "https://api.sb/ledgerlark.com/startups/startup_1", "$type": "Startup", "name": "LedgerLark", "domain": "https://ledgerlark.com", "launchedAt": "2026-10-22T12:00:00Z", "template": "Example template", "idea": "Example idea", "spendState": "free" } ``` ## Relationships - A Startup **is built by** one [Studio](/business/nouns/studio): a [Studio](/business/nouns/studio) founds and builds its Startups and runs [Plays](/business/nouns/play) across them. `builtBy`, inverse [`builds`](/business/nouns/studio#rel-builds). - A Startup **is built with** many [Builders](/business/nouns/builder): [StartupBuilder](/code/builders/startup) directs [SiteBuilder](/code/builders/site), [SoftwareBuilder](/code/builders/software), [ServiceBuilder](/code/builders/service) and [SalesBuilder](/code/builders/sales), each building one side of a Startup. `builtWith`, inverse [`builds`](/business/nouns/builder#rel-builds). - A Startup **compiles** many [Play Mixes](/business/nouns/play-mix): a Startup compiles one [Play Mix](/business/nouns/play-mix) version a week and keeps every earlier version for the diff. `compiles`, inverse [`startup`](/business/nouns/play-mix#rel-startup). - A Startup **has** many [Domains](/business/nouns/domain): a Startup holds each Domain registration and pays for the hostname. `domains`, inverse [`registeredTo`](/business/nouns/domain#rel-registered-to). - A Startup **employs** many [Agents](/business/nouns/agent): an [Agent](/business/nouns/agent) holds a seat in the Startup and acts within the authority it grants; one Agent can hold seats in many Startups. `employs`, inverse [`employedBy`](/business/nouns/agent#rel-employed-by). - A Startup **extends** many [Startup Templates](/business/nouns/startup-template): a Startup inherits a [Startup Template](/business/nouns/startup-template)’s definition, pinned to a [Version](/business/nouns/version) it upgrades through a [Change](/business/nouns/change). `extends`, inverse [`startups`](/business/nouns/startup-template#rel-startups). - A Startup **has** many [Forecasts](/business/nouns/forecast): the default-alive check writes a [Forecast](/business/nouns/forecast) every week and after every large money [Decision](/business/nouns/decision); the latest sets the spend state. `forecasts`, inverse [`startup`](/business/nouns/forecast#rel-startup). - A Startup **funds** many [Demand Budgets](/business/nouns/demand-budget): a Startup commits monthly [Demand Budgets](/business/nouns/demand-budget), each with a target and a stop rule. `funds`, inverse [`fundedBy`](/business/nouns/demand-budget#rel-funded-by). - A Startup **is held by** one [Company](/business/nouns/company): the holding [Company](/business/nouns/company) is the Startup’s owner of record: it signs its [Agreements](/business/nouns/agreement) and owns its profit rights. `heldBy`, inverse [`holds`](/business/nouns/company#rel-holds). - A Startup **makes** many [Products](/business/nouns/product): each [Product](/business/nouns/product) belongs to exactly one Startup, which builds it and stands behind its promise. `makes`, inverse [`madeBy`](/business/nouns/product#rel-made-by). - A Startup **has** many [Markets](/business/nouns/market): where the Startup sells, hires, or keeps books. Each [Market](/business/nouns/market) wakes its floor rows. `markets`, inverse [`startups`](/business/nouns/market#rel-startups). - A Startup **must reach** one [Minimum Success Criteria](/business/nouns/minimum-success-criteria): the one number that decides whether the Startup keeps running. `mustReach`, inverse [`setFor`](/business/nouns/minimum-success-criteria#rel-set-for). - A Startup **has** many [Offers](/business/nouns/offer): each [Offer](/business/nouns/offer) has one maker, which earns its revenue and answers for its terms. `offers`, inverse [`offeredBy`](/business/nouns/offer#rel-offered-by). - A Startup **operates under** many [Agreements](/business/nouns/agreement): the [Agreements](/business/nouns/agreement) a Startup operates under travel with it when it graduates or sells. `operatesUnder`, inverse [`covers`](/business/nouns/agreement#rel-covers). - A Startup **has** many [Portfolios](/business/nouns/portfolio): a Startup can sit in many [Portfolios](/business/nouns/portfolio), each with its own membership: held, owned, contracted or made. `portfolios`, inverse [`includesStartup`](/business/nouns/portfolio#rel-includes-startup). - A Startup **pursues** one [Idea](/business/nouns/idea): many Startups can test one [Idea](/business/nouns/idea) side by side; the Idea outlives each Startup that pursues it. `pursues`, inverse [`pursuedBy`](/business/nouns/idea#rel-pursued-by). - A Startup **has** many [Recovery Objectives](/business/nouns/recovery-objective): one [Recovery Objective](/business/nouns/recovery-objective) for each [Capability](/business/nouns/capability) the Startup depends on. `recoveryObjectives`, inverse [`startup`](/business/nouns/recovery-objective#rel-startup). - A Startup **has** many [Risks](/business/nouns/risk): the [Risks](/business/nouns/risk) scored for one Startup, open and closed. `risks`, inverse [`startup`](/business/nouns/risk#rel-startup). - A Startup **runs** many [Systems](/business/nouns/system): a Startup runs its work on headless [Systems](/business/nouns/system), such as CRM or billing, that every Startup shares. `runs`, inverse [`runBy`](/business/nouns/system#rel-run-by). - A Startup **serves** many [Customers](/business/nouns/customer): a Startup serves every party that has accepted one of its [Offers](/business/nouns/offer). `serves`, inverse [`servedBy`](/business/nouns/customer#rel-served-by). - A Startup **states** many [Hypotheses](/business/nouns/hypothesis): a Startup states [Hypotheses](/business/nouns/hypothesis) about itself, the Founding Hypothesis first, each settled by a [Metric](/business/nouns/metric) and a threshold. `states`, inverse [`statedBy`](/business/nouns/hypothesis#rel-stated-by). - A Startup **targets** many [ICPs](/business/nouns/icp): a Startup is built to win its [ICPs](/business/nouns/icp); its [Offers](/business/nouns/offer), [Story](/business/nouns/story) and [Plays](/business/nouns/play) compile toward them. `targets`, inverse [`targetedBy`](/business/nouns/icp#rel-targeted-by). - A Startup **has** many [Teams](/business/nouns/team): a [Team](/business/nouns/team) does its one kind of work for every Startup it serves; a Startup wakes a Team when its trigger [Event](/business/nouns/event) happens. `teams`, inverse [`serves`](/business/nouns/team#rel-serves). ## Lifecycle | State | Meaning | Moves to | | --- | --- | --- | | `idea` (first) | Idea is the state of a Startup that states its Idea and who pays, before any build work starts. | `building` by [Startup.build](/business/nouns/startup/build) | | `building` | Building is the state of a Startup whose Agents build its Brand, Products, Offers, site, API, and MCP server from its template. | `live` by [Startup.launch](/business/nouns/startup/launch); `dormant` by [Startup.pause](/business/nouns/startup/pause) | | `live` | Live is the state of a Startup that is publicly reachable and takes money from Customers for at least one Offer. | `repeatable` by [Startup.advance](/business/nouns/startup/advance); `hold` by [Startup.hold](/business/nouns/startup/hold); `graduate` by [Startup.graduate](/business/nouns/startup/graduate); `sell` by [Startup.sell](/business/nouns/startup/sell); `dormant` by [Startup.pause](/business/nouns/startup/pause); `building` by [Startup.pivot](/business/nouns/startup/pivot) | | `repeatable` | Repeatable is the state of a Startup whose Customers arrive, pay, and stay, while its work runs without its founder. | `scale` by [Startup.advance](/business/nouns/startup/advance); `hold` by [Startup.hold](/business/nouns/startup/hold); `graduate` by [Startup.graduate](/business/nouns/startup/graduate); `sell` by [Startup.sell](/business/nouns/startup/sell); `dormant` by [Startup.pause](/business/nouns/startup/pause) | | `scale` | Scale is the state of a Startup that compounds: Customers stay and expand, demand comes from several sources, and margins hold. | `hold` by [Startup.hold](/business/nouns/startup/hold); `graduate` by [Startup.graduate](/business/nouns/startup/graduate); `sell` by [Startup.sell](/business/nouns/startup/sell) | | `hold` | Hold is the state of a Startup that keeps operating and serving Customers while its owner adds no new investment. | `repeatable` by [Startup.advance](/business/nouns/startup/advance); `scale` by [Startup.advance](/business/nouns/startup/advance); `graduate` by [Startup.graduate](/business/nouns/startup/graduate); `sell` by [Startup.sell](/business/nouns/startup/sell); `dormant` by [Startup.pause](/business/nouns/startup/pause) | | `graduate` | Graduate is the state of a Startup that leaves its studio for a company of its own, keeping its Brand, Customers, and records. | None: it ends here. | | `sell` | Sell is the state of a Startup whose owner has agreed to sell it, with its Brand, domain, Customers, and records. | None: it ends here. | | `dormant` | Dormant is the state of a Startup with no work running on it, whose records, site, and domain stay kept until it returns to Live. | `live` by [Startup.resume](/business/nouns/startup/resume) | ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Startup.advance](/business/nouns/startup/advance) | Advance moves a Startup to its next Lifecycle state once every entry check of that state passes. | [Agent](/business/nouns/agent) | [`Startup.advanced`](/business/events/Startup.advanced) | None. | | [Startup.build](/business/nouns/startup/build) | Build provisions the Systems, Sites and Interfaces a Startup’s definition declares, and moves the Startup to Building. | [Engineering Lead](/agents/engineering/engineering-lead) | [`Startup.built`](/business/events/Startup.built) | None. | | [Startup.claim](/business/nouns/startup/claim) | Claim binds a provisional Startup to a verified owner, which enables payments and every Verb that moves money. | [Human](/business/nouns/human) | [`Startup.claimed`](/business/events/Startup.claimed) | None. | | [Startup.clone](/business/nouns/startup/clone) | Clone copies a Startup’s definition into a new Startup once, with no link back to the source. | [Agent](/business/nouns/agent) | [`Startup.cloned`](/business/events/Startup.cloned) | None. | | [Startup.graduate](/business/nouns/startup/graduate) | Graduate moves a Startup to a Company of its own, with its Customers, Domains and records intact. | [Founder](/agents/founding/founder) | [`Startup.graduated`](/business/events/Startup.graduated) | One-way (money, customer): `send`, `do` | | [Startup.hold](/business/nouns/startup/hold) | Hold keeps a Startup running in its current Lifecycle state with no new investment from the Studio. | [Strategist](/agents/founding/strategist) | [`Startup.held`](/business/events/Startup.held) | None. | | [Startup.import](/business/nouns/startup/import) | Import builds a new Startup from an existing business’s definition: its Offers, Pages, Nouns and Processes. | [Integration Engineer](/agents/engineering/integration-engineer) | [`Startup.imported`](/business/events/Startup.imported) | None. | | [Startup.launch](/business/nouns/startup/launch) | Launch puts a Startup live on its domain, serving its Offers to Customers. | [Founder](/agents/founding/founder) | [`Startup.launched`](/business/events/Startup.launched) | None. | | [Startup.pause](/business/nouns/startup/pause) | Pause moves a Startup to Dormant: its scheduled Workflows stop, and its Sites and records stay in place. | [Founder](/agents/founding/founder) | [`Startup.paused`](/business/events/Startup.paused) | None. | | [Startup.pivot](/business/nouns/startup/pivot) | Pivot records a Decision that moves a Live Startup back to Building under a new Founding Hypothesis version. | [Founder](/agents/founding/founder) | [`Startup.pivoted`](/business/events/Startup.pivoted) | One-way (customer): `send`, `do` | | [Startup.read](/business/nouns/startup/read) | Read compiles a Startup’s records into one scoped room, such as a diligence room, with every number citing its Proof. | [Agent](/business/nouns/agent) | [`Startup.read`](/business/events/Startup.read) | Two-way: `try`, `send`, `do` | | [Startup.resume](/business/nouns/startup/resume) | Resume returns a Dormant Startup to the Lifecycle state it held when it paused. | [Founder](/agents/founding/founder) | [`Startup.resumed`](/business/events/Startup.resumed) | None. | | [Startup.sell](/business/nouns/startup/sell) | Sell transfers a Startup, with its Customers, Domains and records, to a buyer under a signed Agreement. | [Founder](/agents/founding/founder) | [`Startup.sold`](/business/events/Startup.sold) | One-way (money, customer): `send`, `do` | | [Startup.create](/business/nouns/startup/create) | Creates a Startup. Inherited from [Noun](/business/nouns/noun). | None. | `Startup.created` | Two-way: `try`, `send`, `do` | | [Startup.get](/business/nouns/startup/get) | Returns one Startup by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Startup.list](/business/nouns/startup/list) | Returns Startups, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Startup.update](/business/nouns/startup/update) | Changes the given properties of a Startup. Inherited from [Noun](/business/nouns/noun). | None. | `Startup.updated` | Two-way: `try`, `send`, `do` | | [Startup.delete](/business/nouns/startup/delete) | Deletes a Startup; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Startup.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Startup.create` | Yes | Yes | Yes | No | | `Startup.get` | Yes | Yes | Yes | Yes | | `Startup.list` | Yes | Yes | Yes | Yes | | `Startup.update` | Yes | Yes | Yes | No | | `Startup.delete` | Yes | Yes | Yes | No | | `Startup.advance` | Yes | Yes | Yes | No | | `Startup.build` | Yes | Yes | Yes | No | | `Startup.claim` | Yes | Yes | Yes | No | | `Startup.clone` | Yes | Yes | Yes | No | | `Startup.graduate` | Yes | No | No | No | | `Startup.hold` | Yes | Yes | Yes | No | | `Startup.import` | Yes | Yes | Yes | No | | `Startup.launch` | Yes | Yes | Yes | No | | `Startup.pause` | Yes | Yes | Yes | No | | `Startup.pivot` | Yes | No | No | No | | `Startup.read` | Yes | Yes | Yes | No | | `Startup.resume` | Yes | Yes | Yes | No | | `Startup.sell` | Yes | No | No | No | ## Call it **Ask** ```text Launch QuietCopy. ``` **API** ```bash curl -X POST https://api.sb/quietcopy.com/startups/startup_1/launch \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/quietcopy.com", "startup": { "$id": "https://api.sb/quietcopy.com/startups/startup_1", "$type": "Startup", "name": "QuietCopy" }, "action": { "$id": "https://api.sb/quietcopy.com/actions/action_1", "operation": "Startup.launch", "status": "done" }, "links": { "self": "https://api.sb/quietcopy.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const startup = await $.Startup.launch({ startup: 'startup_1' }) ``` **CLI** ```bash npx startup-builder do Startup.launch --json '{"startup":"startup_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Startup.launch({ startup: 'startup_1' })" } } ``` ## Example A debt-recovery Startup shares its holding Company with two siblings. It keeps its own Customers, Offers and P&L, so [`Startup.sell`](/business/nouns/startup/sell) transfers it to a buyer without touching the other two. # launch URL: /business/nouns/startup/launch · Id: `verb:Startup.launch` · Call: `await $.Startup.launch({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Launch puts a Startup live on its domain, serving its Offers to Customers. Launch puts a [Startup](/business/nouns/startup) live on its domain, serving its [Offers](/business/nouns/offer) to [Customers](/business/nouns/customer). ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `startup` | [Startup](/business/nouns/startup) | Yes | The Startup to launch. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `startup` | [Startup](/business/nouns/startup) | Yes | The Startup, now live. | ## Effects - Emits [`Startup.launched`](/business/events/Startup.launched). - Performed by the [Founder](/agents/founding/founder). - Runs the entry checks of Live, and refuses when any check fails. - Sets `launchedAt` on the Startup. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | Offers published (`live-offers`) | [`refused`](/code/api/errors/refused) | Publish an Offer with a price and terms. | [Offer.publish](/business/nouns/offer/publish) | | Work defined (`live-work`) | [`refused`](/code/api/errors/refused) | Give every published Offer a Workflow with each step assigned. | [Workflow.create](/business/nouns/workflow/create) | | People assigned (`live-people`) | [`refused`](/code/api/errors/refused) | Seat an Agent or a person in every Role the Workflows need. | [Role.staff](/business/nouns/role/staff) | | Site published (`live-site`) | [`refused`](/code/api/errors/refused) | Publish the home, pricing, terms, and privacy Pages. | [Version.deploy](/business/nouns/version/deploy) | | Test run passed (`live-test-run`) | [`refused`](/code/api/errors/refused) | Have a sample Customer accept every published Offer in test. | [Offer.accept](/business/nouns/offer/accept) | | Portal ready (`live-portal`) | [`refused`](/code/api/errors/refused) | Build the Startup so the Portal serves every Customer record. | [Startup.build](/business/nouns/startup/build) | | Agent API open (`live-agent-api`) | [`refused`](/code/api/errors/refused) | Build the Startup and fix each conformance failure it names. | [Startup.build](/business/nouns/startup/build) | | Payouts connected (`live-payouts`) | [`refused`](/code/api/errors/refused) | Have a person claim the Startup and finish payouts onboarding. | [Startup.claim](/business/nouns/startup/claim) | | Address resolves (`live-address`) | [`refused`](/code/api/errors/refused) | Connect the Domain, wait for its certificate, and check `walletsEnabled`. | [Domain.connect](/business/nouns/domain/connect) | | Five slots at Commitment (`live-slots`) | [`refused`](/code/api/errors/refused) | Run the cheapest test on each slot below Commitment, such as a fake door on the reserve page. | [Experiment.start](/business/nouns/experiment/start) | | Sources secured (`live-sources`, [Dataset API](/products/templates/dataset-api), [Directory](/products/templates/directory) only) | [`refused`](/code/api/errors/refused) | Record a licensed, crawled, or synthetic Source for every Dataset. | [Source.create](/business/nouns/source/create) | | Evals passing (`live-evals`, [Agent as a Service](/products/templates/agent-as-a-service) only) | [`refused`](/code/api/errors/refused) | Run the Evals again after fixing each failing task type. | [Action.evaluate](/business/nouns/action/evaluate) | | SLA published (`live-sla`, [Services-as-Software](/products/templates/services-as-software), [E2E managed service](/products/templates/managed-service) only) | [`refused`](/code/api/errors/refused) | State the outcome, the SLA, and the remedy on every service Offer. | [Offer.publish](/business/nouns/offer/publish) | | Supply seeded (`live-supply`, [Marketplace](/products/templates/marketplace), [Licensed-human marketplace](/products/templates/licensed-marketplace) only) | [`refused`](/code/api/errors/refused) | Onboard the first Suppliers and have each accept the supplier terms. | [Human.onboard](/business/nouns/human/onboard) | | Credentials verified (`live-credentials`, [Licensed-human marketplace](/products/templates/licensed-marketplace) only) | [`refused`](/code/api/errors/refused) | Verify a current credential for each Supplier in each jurisdiction served. | [Credential.verify](/business/nouns/credential/verify) | | Human steps staffed (`live-human-loop`, [E2E managed service](/products/templates/managed-service) only) | [`refused`](/code/api/errors/refused) | Seat a person in every human delivery step, with a response time. | [Role.staff](/business/nouns/role/staff) | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Startup.launch](/business/nouns/startup/launch) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Medium: two-way, visible | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | 1 business hour, in which a watcher can pause, redirect or cancel it; then it runs. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example An [Agent](/business/nouns/agent) launches a Startup once its site and first Offer are ready, and Customers can accept that Offer from then on. **Ask** ```text Launch QuietCopy. ``` **API** ```bash curl -X POST https://api.sb/quietcopy.com/startups/startup_1/launch \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/quietcopy.com", "startup": { "$id": "https://api.sb/quietcopy.com/startups/startup_1", "$type": "Startup", "name": "QuietCopy" }, "action": { "$id": "https://api.sb/quietcopy.com/actions/action_1", "operation": "Startup.launch", "status": "done" }, "links": { "self": "https://api.sb/quietcopy.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const startup = await $.Startup.launch({ startup: 'startup_1' }) ``` **CLI** ```bash npx startup-builder do Startup.launch --json '{"startup":"startup_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Startup.launch({ startup: 'startup_1' })" } } ``` Guides that call it: [Launch my business](/business/launch-my-business). # pause URL: /business/nouns/startup/pause · Id: `verb:Startup.pause` · Call: `await $.Startup.pause({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Pause moves a Startup to Dormant: its scheduled Workflows stop, and its Sites and records stay in place. Pause moves a [Startup](/business/nouns/startup) to Dormant: its scheduled [Workflows](/business/nouns/workflow) stop, and its [Sites](/business/nouns/site) and records stay in place. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `startup` | [Startup](/business/nouns/startup) | Yes | The Startup to pause. | | `reason` | `text` | No | Why the Startup pauses. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `startup` | [Startup](/business/nouns/startup) | Yes | The Startup, now Dormant. | ## Effects - Emits [`Startup.paused`](/business/events/Startup.paused). - Performed by the [Founder](/agents/founding/founder). - Stops every scheduled Workflow. - Records the state the Startup held, for `resume`. - Deletes nothing. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Startup.pause](/business/nouns/startup/pause) | | The record is not in a state that allows this Verb, so the call is refused. | [`refused`](/code/api/errors/refused) | Read the record, run the Verb that moves it to an allowed state, then retry. | [Startup.pause](/business/nouns/startup/pause) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Pause ShiftNote. ``` **API** ```bash curl -X POST https://api.sb/shiftnote.app/startups/startup_1/pause \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/shiftnote.app", "startup": { "$id": "https://api.sb/shiftnote.app/startups/startup_1", "$type": "Startup", "name": "ShiftNote" }, "action": { "$id": "https://api.sb/shiftnote.app/actions/action_1", "operation": "Startup.pause", "status": "done" }, "links": { "self": "https://api.sb/shiftnote.app/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const startup = await $.Startup.pause({ startup: 'startup_1' }) ``` **CLI** ```bash npx startup-builder do Startup.pause --json '{"startup":"startup_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Startup.pause({ startup: 'startup_1' })" } } ``` Next: [`Company.dissolve`](/business/nouns/company/dissolve) (in `guide:wind-down-my-startup`). Guides that call it: [Wind down my startup](/business/wind-down-my-startup). # pivot URL: /business/nouns/startup/pivot · Id: `verb:Startup.pivot` · Call: `await $.Startup.pivot({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Pivot records a Decision that moves a Live Startup back to Building under a new Founding Hypothesis version. Pivot records a [Decision](/business/nouns/decision) that moves a Live [Startup](/business/nouns/startup) back to Building under a new Founding Hypothesis version. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `startup` | [Startup](/business/nouns/startup) | Yes | The Live Startup. | | `decision` | [Decision](/business/nouns/decision) | Yes | The pivot Decision, citing the Evidence behind it. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `startup` | [Startup](/business/nouns/startup) | Yes | The Startup, now Building. | ## Effects - Emits [`Startup.pivoted`](/business/events/Startup.pivoted). - Performed by the [Founder](/agents/founding/founder). - One-way (customer): it waits out its delay window, and runs in the `send` and `do` modes. - Bumps the Founding Hypothesis version; the pivot is the diff between the two versions. - Recompiles Site copy, Offers, Prices, and Plays from the new version. - Keeps serving existing Customers until each Offer they hold ends on its own terms. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Startup.pivot](/business/nouns/startup/pivot) | ## When it waits | Gate | Default | | --- | --- | | Decision class | High: one-way, broad (customer) | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | 1 business day, in which a watcher can pause, redirect or cancel it; then it runs. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Pivot PatentPad with a decision. ``` **API** ```bash curl -X POST https://api.sb/patentpad.com/startups/startup_1/pivot \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"decision":"decision_1"}' ``` ```json { "api": "https://api.sb/patentpad.com", "startup": { "$id": "https://api.sb/patentpad.com/startups/startup_1", "$type": "Startup", "name": "PatentPad" }, "action": { "$id": "https://api.sb/patentpad.com/actions/action_1", "operation": "Startup.pivot", "status": "done" }, "links": { "self": "https://api.sb/patentpad.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const startup = await $.Startup.pivot({ startup: 'startup_1', decision: 'decision_1' }) ``` **CLI** ```bash npx startup-builder do Startup.pivot --json '{"startup":"startup_1","decision":"decision_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Startup.pivot({ startup: 'startup_1', decision: 'decision_1' })" } } ``` # read URL: /business/nouns/startup/read · Id: `verb:Startup.read` · Call: `await $.Startup.read({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Read compiles a Startup’s records into one scoped room, such as a diligence room, with every number citing its Proof. Read compiles a [Startup](/business/nouns/startup)’s records into one scoped room, such as a diligence room, with every number citing its [Proof](/business/nouns/proof). ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `startup` | [Startup](/business/nouns/startup) | Yes | The Startup to read. | | `scope` | `string` | Yes | What the room holds: `diligence` for a raise, a sale or an LP look-through. | | `reader` | [Party](/business/nouns/party) | No | Who reads it; access is a Permission that expires, readable over MCP. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `room` | `json` | Yes | Statements, Metrics, cap table, Agreements in force, Control Proofs and open Disputes, each linked to its record. | | `gaps` | `json` | Yes | Each failed readiness check with its fix, such as a Period still open. | | `startup` | [Startup](/business/nouns/startup) | Yes | The Startup the room was compiled from. | ## Effects - Emits [`Startup.read`](/business/events/Startup.read). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Compiles from records and never from uploads: each document is its signed Version. - Runs the readiness checks: three Periods closed in a row, cap table reconciled to signed Agreements, IP assigned, Controls passing. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Startup.read](/business/nouns/startup/read) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Read PatentPad. ``` **API** ```bash curl -X POST https://api.sb/patentpad.com/startups/startup_1/read \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"scope":"diligence"}' ``` ```json { "api": "https://api.sb/patentpad.com", "room": {}, "gaps": {}, "startup": { "$id": "https://api.sb/patentpad.com/startups/startup_1", "$type": "Startup", "name": "PatentPad" }, "action": { "$id": "https://api.sb/patentpad.com/actions/action_1", "operation": "Startup.read", "status": "done" }, "links": { "self": "https://api.sb/patentpad.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { room, gaps, startup } = await $.Startup.read({ startup: 'startup_1', scope: 'diligence' }) ``` **CLI** ```bash npx startup-builder do Startup.read --json '{"startup":"startup_1","scope":"diligence"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Startup.read({ startup: 'startup_1', scope: 'diligence' })" } } ``` # resume URL: /business/nouns/startup/resume · Id: `verb:Startup.resume` · Call: `await $.Startup.resume({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Resume returns a Dormant Startup to the Lifecycle state it held when it paused. Resume returns a Dormant [Startup](/business/nouns/startup) to the [Lifecycle](/business/nouns/lifecycle) state it held when it paused. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `startup` | [Startup](/business/nouns/startup) | Yes | The Dormant Startup. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `startup` | [Startup](/business/nouns/startup) | Yes | The Startup in its prior state. | ## Effects - Emits [`Startup.resumed`](/business/events/Startup.resumed). - Performed by the [Founder](/agents/founding/founder). - Restarts every scheduled Workflow. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Startup.resume](/business/nouns/startup/resume) | | The record is not in a state that allows this Verb, so the call is refused. | [`refused`](/code/api/errors/refused) | Read the record, run the Verb that moves it to an allowed state, then retry. | [Startup.resume](/business/nouns/startup/resume) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Resume QuietCopy. ``` **API** ```bash curl -X POST https://api.sb/quietcopy.com/startups/startup_1/resume \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/quietcopy.com", "startup": { "$id": "https://api.sb/quietcopy.com/startups/startup_1", "$type": "Startup", "name": "QuietCopy" }, "action": { "$id": "https://api.sb/quietcopy.com/actions/action_1", "operation": "Startup.resume", "status": "done" }, "links": { "self": "https://api.sb/quietcopy.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const startup = await $.Startup.resume({ startup: 'startup_1' }) ``` **CLI** ```bash npx startup-builder do Startup.resume --json '{"startup":"startup_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Startup.resume({ startup: 'startup_1' })" } } ``` # sell URL: /business/nouns/startup/sell · Id: `verb:Startup.sell` · Call: `await $.Startup.sell({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Sell transfers a Startup, with its Customers, Domains and records, to a buyer under a signed Agreement. Sell transfers a [Startup](/business/nouns/startup), with its [Customers](/business/nouns/customer), [Domains](/business/nouns/domain) and records, to a buyer under a signed [Agreement](/business/nouns/agreement). ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `startup` | [Startup](/business/nouns/startup) | Yes | The Startup to sell. | | `agreement` | [Agreement](/business/nouns/agreement) | Yes | The signed sale Agreement. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `startup` | [Startup](/business/nouns/startup) | Yes | The Startup, held by the buyer. | ## Effects - Emits [`Startup.sold`](/business/events/Startup.sold). - Performed by the [Founder](/agents/founding/founder). - One-way (money, customer): it waits out its delay window, and runs in the `send` and `do` modes. - Transfers every Domain and payment account to the buyer. - Requires a human signature, because it moves equity. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | Own Domain (`sell-domain`) | [`refused`](/code/api/errors/refused) | Move each Domain into the Startup’s own registrar account and wait out any transfer lock; the account then moves whole at closing. | [Domain.transfer](/business/nouns/domain/transfer) | | Own payments account (`sell-payments`) | [`refused`](/code/api/errors/refused) | Move payments to a Stripe account the Startup holds alone. | [Startup.claim](/business/nouns/startup/claim) | | Agreements transfer (`sell-agreements`) | [`refused`](/code/api/errors/refused) | Sign assignable terms for each Agreement that names the Startup. | [Agreement.sign](/business/nouns/agreement/sign) | | Data exports (`sell-export`) | [`refused`](/code/api/errors/refused) | Import the latest export into an empty namespace and compare the replayed state. | [Startup.import](/business/nouns/startup/import) | | No shared credentials (`sell-credentials`) | [`refused`](/code/api/errors/refused) | Replace every shared key or login with one the Startup holds alone. | None. | | Sale agreed (`sell-agreed`) | [`refused`](/code/api/errors/refused) | A signed sale agreement names the buyer and schedules the transfer of Brand, domain, Customers, and records. | None. | | The input does not match the schema of the operation. | [`invalid-input`](/code/api/errors/invalid-input) | Read the schema of the operation, then send every required field with the right type. | [Startup.sell](/business/nouns/startup/sell) | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Startup.sell](/business/nouns/startup/sell) | ## When it waits | Gate | Default | | --- | --- | | Decision class | High: one-way, broad (money, customer) | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | 1 business day, in which a watcher can pause, redirect or cancel it; then it runs. | | Limit | The spend [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) or [Mandate](/business/nouns/mandate) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Sell PatentPad with an agreement. ``` **API** ```bash curl -X POST https://api.sb/patentpad.com/startups/startup_1/sell \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"agreement":"agreement_1"}' ``` ```json { "api": "https://api.sb/patentpad.com", "startup": { "$id": "https://api.sb/patentpad.com/startups/startup_1", "$type": "Startup", "name": "PatentPad" }, "action": { "$id": "https://api.sb/patentpad.com/actions/action_1", "operation": "Startup.sell", "status": "done" }, "links": { "self": "https://api.sb/patentpad.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const startup = await $.Startup.sell({ startup: 'startup_1', agreement: 'agreement_1' }) ``` **CLI** ```bash npx startup-builder do Startup.sell --json '{"startup":"startup_1","agreement":"agreement_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Startup.sell({ startup: 'startup_1', agreement: 'agreement_1' })" } } ``` # Statement URL: /business/nouns/statement · Id: `noun:statement` > A Statement is a report computed from Entries for one Period under a Policy, such as a P&L, a balance sheet or a payout statement. A Statement is a report computed from [Entries](/business/nouns/entry) for one [Period](/business/nouns/period) under a [Policy](/business/nouns/policy), such as a P&L, a balance sheet or a payout statement. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `kind` | `string` | Yes | Which report: `profitAndLoss`, `balanceSheet`, `cashFlow`, `payout` for a Supplier, or `capitalAccount` for a Fund investor. | | `period` | [Period](/business/nouns/period) | Yes | The Period it reports. | | `scope` | `string` | Yes | Whose books it covers: one Startup, one Company, or a whole Portfolio. | | `lines` | `json` | Yes | The computed lines, with captive revenue from sibling Startups shown both in and out. | | `party` | [Party](/business/nouns/party) | No | The Supplier, Partner or investor a `payout` or `capitalAccount` Statement is addressed to. | ## Object ```json { "$id": "https://api.sb/shiftnote.app/statements/statement_1", "$type": "Statement", "kind": "profitAndLoss", "period": "period_1", "scope": "startup", "lines": {}, "party": "party_1" } ``` ## Relationships - A Statement **reports** one [Period](/business/nouns/period): a Statement reports one [Period](/business/nouns/period); each closed Period carries its P&L, balance sheet and cash flow. `reports`, inverse [`statements`](/business/nouns/period#rel-statements). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Statement.get](/business/nouns/statement/get) | Returns one Statement by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Statement.list](/business/nouns/statement/list) | Returns Statements, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | A Statement is kept forever and never edited: it has no `update` or `delete`. ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Statement.get` | Yes | Yes | Yes | Yes | | `Statement.list` | Yes | Yes | Yes | Yes | ## Call it **Ask** ```text Show me the latest statement. ``` **API** ```bash curl https://api.sb/routewise.dev/statements/statement_1 \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/routewise.dev", "$type": "Statement", "$id": "https://api.sb/routewise.dev/statements/statement_1", "statement": { "$id": "https://api.sb/routewise.dev/statements/statement_1", "$type": "Statement", "kind": "profitAndLoss", "period": "period_1", "scope": "startup", "lines": {} }, "links": { "self": "https://api.sb/routewise.dev/statements/statement_1", "up": "https://api.sb/routewise.dev/statements" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const statement = await $.Statement.get({ id: 'statement_1' }) ``` **CLI** ```bash npx startup-builder do Statement.get --json '{"id":"statement_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Statement.get({ id: 'statement_1' })" } } ``` ## Example At a month's close a [Startup](/business/nouns/startup) gets a `profitAndLoss` Statement computed from its [Entries](/business/nouns/entry). Revenue from a sibling Startup shows as captive, both inside and outside the total. # Story URL: /business/nouns/story · Id: `noun:story` > A Story is the customer narrative for one ICP, compiled from its Founding Hypothesis and Interview quotes, never written by hand. A Story is the customer narrative for one [ICP](/business/nouns/icp), compiled from its Founding Hypothesis and [Interview](/business/nouns/interview) quotes, never written by hand. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `icp` | [ICP](/business/nouns/icp) | Yes | The ICP it speaks to: one Story per ICP. | | `hero` | `text` | Yes | Who the customer is and what they want. | | `problem` | [Problem](/business/nouns/problem) | Yes | The Problem: external, internal, and the villain behind it. | | `guide` | `text` | No | The Startup’s empathy and authority, the authority read from Metrics and Evidence. | | `plan` | `text` | No | Three steps, each naming a declared Event. | | `success` | `text` | No | What the customer gains. | | `failure` | `text` | No | What the customer risks without it. | | `oneLiner` | `string` | No | The Story in one sentence. | | `direct` | [Offer](/business/nouns/offer) | No | The direct call to action: an Offer that makes a Customer. | | `transitional` | [Funnel](/business/nouns/funnel) | No | The transitional call to action: a Funnel opt-in that makes a Lead. | | `from` | `string` | Yes | Lineage: the slot it compiles from, as `Hypothesis#@v`. | | `stance` | `string` | No | The positioning the Positioning tournament chose, graded Behavior; every compiled asset recompiles when it changes. | | `category` | `string` | No | The market category name the Story claims, as answer engines repeat it. | ## Object ```json { "$id": "https://api.sb/ledgerlark.com/stories/story_1", "$type": "Story", "icp": "icp_1", "hero": "Example hero", "problem": "problem_1", "guide": "Example guide", "plan": "Example plan", "success": "Example success", "failure": "Example failure", "oneLiner": "Example one liner", "direct": "offer_1", "transitional": "funnel_1", "from": "Hypothesis#approach@v1", "stance": "headToHead", "category": "Example category" } ``` ## Relationships - A Story **is compiled from** one [Hypothesis](/business/nouns/hypothesis): the Founding Hypothesis whose slots the Story compiles from; a pivot recompiles it. `compiledFrom`, inverse [`stories`](/business/nouns/hypothesis#rel-stories). - A Story **quotes** many [Interviews](/business/nouns/interview): the [Interviews](/business/nouns/interview) whose words the Story reuses. `quotes`, inverse [`quotedIn`](/business/nouns/interview#rel-quoted-in). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Story.create](/business/nouns/story/create) | Creates a Story. Inherited from [Noun](/business/nouns/noun). | None. | `Story.created` | Two-way: `try`, `send`, `do` | | [Story.get](/business/nouns/story/get) | Returns one Story by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Story.list](/business/nouns/story/list) | Returns Stories, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Story.update](/business/nouns/story/update) | Changes the given properties of a Story. Inherited from [Noun](/business/nouns/noun). | None. | `Story.updated` | Two-way: `try`, `send`, `do` | | [Story.delete](/business/nouns/story/delete) | Deletes a Story; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Story.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Story.create` | Yes | Yes | Yes | No | | `Story.get` | Yes | Yes | Yes | Yes | | `Story.list` | Yes | Yes | Yes | Yes | | `Story.update` | Yes | Yes | Yes | No | | `Story.delete` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Add a story to PatentPad with an ICP and a problem. ``` **API** ```bash curl -X POST https://api.sb/patentpad.com/stories \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"icp":"icp_1","hero":"Example hero","problem":"problem_1","from":"Hypothesis#approach@v1"}' ``` ```json { "api": "https://api.sb/patentpad.com", "story": { "$id": "https://api.sb/patentpad.com/stories/story_1", "$type": "Story", "icp": "icp_1", "hero": "Example hero", "problem": "problem_1", "from": "Hypothesis#approach@v1" }, "action": { "$id": "https://api.sb/patentpad.com/actions/action_1", "operation": "Story.create", "status": "done" }, "links": { "self": "https://api.sb/patentpad.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const story = await $.Story.create({ icp: 'icp_1', hero: 'Example hero', problem: 'problem_1', from: 'Hypothesis#approach@v1' }) ``` **CLI** ```bash npx startup-builder do Story.create --json '{"icp":"icp_1","hero":"Example hero","problem":"problem_1","from":"Hypothesis#approach@v1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Story.create({ icp: 'icp_1', hero: 'Example hero', problem: 'problem_1', from: 'Hypothesis#approach@v1' })" } } ``` ## Example A patent-drafting [Startup](/business/nouns/startup) compiles one Story for solo inventors. The hero wants a filed patent, the villain is a $15,000 attorney bill, and the call to action is a $499 draft [Offer](/business/nouns/offer). # Studio URL: /business/nouns/studio · Id: `noun:studio` > A Studio is an organization that builds Startups, holds them through Companies, and runs Plays across its Portfolio. A Studio is an organization that builds [Startups](/business/nouns/startup), holds them through [Companies](/business/nouns/company), and runs [Plays](/business/nouns/play) across its [Portfolio](/business/nouns/portfolio). One Play reaches every Startup a Portfolio query selects. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `name` | `string` | Yes | The name of the Studio. | ## Object ```json { "$id": "https://api.sb/tutorloop.com/studios/studio_1", "$type": "Studio", "name": "TutorLoop" } ``` ## Relationships - A Studio **builds** many [Startups](/business/nouns/startup): a Studio founds and builds its [Startups](/business/nouns/startup) and runs [Plays](/business/nouns/play) across them. `builds`, inverse [`builtBy`](/business/nouns/startup#rel-built-by). - A Studio **controls** many [Companies](/business/nouns/company): a Studio controls the holding [Companies](/business/nouns/company) that are owner of record for its [Startups](/business/nouns/startup). `controls`, inverse [`controlledBy`](/business/nouns/company#rel-controlled-by). - A Studio **manages** many [Portfolios](/business/nouns/portfolio): a Studio allocates attention and money across the members of each [Portfolio](/business/nouns/portfolio) it manages. `manages`, inverse [`managedBy`](/business/nouns/portfolio#rel-managed-by). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Play.apply](/business/nouns/play/apply) | Apply runs a Play across a Portfolio cohort, one wave at a time, measured as an Experiment. | [Marketing Lead](/agents/marketing/marketing-lead) | [`Play.applied`](/business/events/Play.applied) | None. | | [Startup.graduate](/business/nouns/startup/graduate) | Graduate moves a Startup to a Company of its own, with its Customers, Domains and records intact. | [Founder](/agents/founding/founder) | [`Startup.graduated`](/business/events/Startup.graduated) | One-way (money, customer): `send`, `do` | | [Startup.hold](/business/nouns/startup/hold) | Hold keeps a Startup running in its current Lifecycle state with no new investment from the Studio. | [Strategist](/agents/founding/strategist) | [`Startup.held`](/business/events/Startup.held) | None. | | [Startup.sell](/business/nouns/startup/sell) | Sell transfers a Startup, with its Customers, Domains and records, to a buyer under a signed Agreement. | [Founder](/agents/founding/founder) | [`Startup.sold`](/business/events/Startup.sold) | One-way (money, customer): `send`, `do` | | [Studio.create](/business/nouns/studio/create) | Creates a Studio. Inherited from [Noun](/business/nouns/noun). | None. | `Studio.created` | Two-way: `try`, `send`, `do` | | [Studio.get](/business/nouns/studio/get) | Returns one Studio by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Studio.list](/business/nouns/studio/list) | Returns Studios, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Studio.update](/business/nouns/studio/update) | Changes the given properties of a Studio. Inherited from [Noun](/business/nouns/noun). | None. | `Studio.updated` | Two-way: `try`, `send`, `do` | | [Studio.delete](/business/nouns/studio/delete) | Deletes a Studio; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Studio.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Studio.create` | Yes | Yes | Yes | No | | `Studio.get` | Yes | Yes | Yes | Yes | | `Studio.list` | Yes | Yes | Yes | Yes | | `Studio.update` | Yes | Yes | Yes | No | | `Studio.delete` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Add a studio to QuietCopy. ``` **API** ```bash curl -X POST https://api.sb/quietcopy.com/studios \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"name":"QuietCopy"}' ``` ```json { "api": "https://api.sb/quietcopy.com", "studio": { "$id": "https://api.sb/quietcopy.com/studios/studio_1", "$type": "Studio", "name": "QuietCopy" }, "action": { "$id": "https://api.sb/quietcopy.com/actions/action_1", "operation": "Studio.create", "status": "done" }, "links": { "self": "https://api.sb/quietcopy.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const studio = await $.Studio.create({ name: 'QuietCopy' }) ``` **CLI** ```bash npx startup-builder do Studio.create --json '{"name":"QuietCopy"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Studio.create({ name: 'QuietCopy' })" } } ``` ## Example A Studio builds 40 Startups and holds them through two Companies. It runs [`Play.apply`](/business/nouns/play/apply) once, and a comparison-pages Play starts on the 12 software Startups already selling. # Subscription URL: /business/nouns/subscription · Id: `noun:subscription` > A Subscription is a Customer’s standing acceptance of an Offer, billed each Period until canceled. A Subscription is a [Customer](/business/nouns/customer)’s standing acceptance of a recurring [Offer](/business/nouns/offer), renewed and billed each period until canceled. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `status` | `string` | Yes | One of `active`, `trialing`, `pastDue`, `paused`, `incomplete`, or `canceled`. | | `renewsAt` | `datetime` | No | When it next renews. | | `quantity` | `integer` | No | How many units of the Offer’s Price it holds, such as 12 members; 1 by default. | | `trialEndsAt` | `datetime` | No | When a trial ends and the first paid period starts. | | `termEndsAt` | `datetime` | No | When a committed term ends; the Renewal and the renewal notice read it. | ## Object ```json { "$id": "https://api.sb/routewise.dev/subscriptions/subscription_1", "$type": "Subscription", "status": "active", "renewsAt": "2026-10-22T12:00:00Z", "quantity": 1, "trialEndsAt": "2026-10-22T12:00:00Z", "termEndsAt": "2026-10-22T12:00:00Z" } ``` ## Relationships - A Subscription **bills** many [Invoices](/business/nouns/invoice): the [Invoices](/business/nouns/invoice) the Subscription issues, one for each period it renews. `bills`, inverse [`billedFor`](/business/nouns/invoice#rel-billed-for). - A Subscription **has** one [Quote](/business/nouns/quote): the Subscription for a [Quote](/business/nouns/quote)’s recurring lines, started when the [Customer](/business/nouns/customer) accepts it. `quote`, inverse [`startsSubscription`](/business/nouns/quote#rel-starts-subscription). - A Subscription **has** many [Renewals](/business/nouns/renewal): each [Renewal](/business/nouns/renewal) decides one term of one Subscription; a Subscription has one Renewal per term. `renewals`, inverse [`renews`](/business/nouns/renewal#rel-renews). - A Subscription **renews** one [Offer](/business/nouns/offer): a Subscription bills one recurring [Offer](/business/nouns/offer) each [Period](/business/nouns/period) until canceled. `renews`, inverse [`subscriptions`](/business/nouns/offer#rel-subscriptions). - A Subscription’s **subscriber** is one [Customer](/business/nouns/customer): a [Customer](/business/nouns/customer) holds Subscriptions, each billed once per [Period](/business/nouns/period). `subscriber`, inverse [`maintains`](/business/nouns/customer#rel-maintains). ## Lifecycle | State | Meaning | Moves to | | --- | --- | --- | | `incomplete` (first) | The Subscription exists and its first period is billed but not yet paid. | `trialing` by [Offer.trial](/business/nouns/offer/trial); `active` on [`Invoice.collected`](/business/events/Invoice.collected) when the Invoice bills this Subscription’s first period; `canceled` by [Subscription.unsubscribe](/business/nouns/subscription/unsubscribe) | | `trialing` | The Customer uses the Offer free until `trialEndsAt`. | `active` by [Subscription.renew](/business/nouns/subscription/renew); `canceled` by [Subscription.unsubscribe](/business/nouns/subscription/unsubscribe) | | `active` | The Subscription renews each period and its Entitlements hold. | `paused` by [Subscription.pause](/business/nouns/subscription/pause); `pastDue` on [`Invoice.overdue`](/business/nouns/invoice#invoiceoverdue) when the Invoice bills this Subscription; `canceled` by [Subscription.unsubscribe](/business/nouns/subscription/unsubscribe) | | `pastDue` | A renewal Invoice is unpaid while its retries run; Entitlements still hold. | `active` on [`Invoice.collected`](/business/events/Invoice.collected) when the Invoice bills this Subscription; `canceled` on [`Invoice.overdue`](/business/nouns/invoice#invoiceoverdue) when every retry on the Startup’s retry schedule has failed | | `paused` | Billing and Entitlements stop until the pause ends, and the term moves by the paused days. | `active` by [Subscription.resume](/business/nouns/subscription/resume); `canceled` by [Subscription.unsubscribe](/business/nouns/subscription/unsubscribe) | | `canceled` | The Subscription has ended; the Customer starts again with a new one. | None: it ends here. | ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Subscription.keep](/business/nouns/subscription/keep) | Keep takes back a cancel before the period closes, so the Subscription renews on its date at the same terms. | [Billing Specialist](/agents/finance/billing-specialist) | [`Subscription.kept`](/business/events/Subscription.kept) | Two-way: `try`, `send`, `do` | | [Subscription.pause](/business/nouns/subscription/pause) | Pause stops billing and Entitlements on a Subscription until a date, without ending it. | [Billing Specialist](/agents/finance/billing-specialist) | [`Subscription.paused`](/business/events/Subscription.paused) | Two-way: `try`, `send`, `do` | | [Subscription.renew](/business/nouns/subscription/renew) | Renew starts a Subscription’s next period and bills it at the Offer Version the Customer accepted. | [Billing Specialist](/agents/finance/billing-specialist) | [`Subscription.renewed`](/business/events/Subscription.renewed) | Two-way: `try`, `send`, `do` | | [Subscription.resize](/business/nouns/subscription/resize) | Resize changes how many units a Subscription holds and prorates the current period. | [Billing Specialist](/agents/finance/billing-specialist) | [`Subscription.resized`](/business/events/Subscription.resized) | Two-way: `try`, `send`, `do` | | [Subscription.resume](/business/nouns/subscription/resume) | Resume restarts billing and Entitlements on a paused Subscription before its pause ends. | [Billing Specialist](/agents/finance/billing-specialist) | [`Subscription.resumed`](/business/events/Subscription.resumed) | Two-way: `try`, `send`, `do` | | [Subscription.switch](/business/nouns/subscription/switch) | Switch moves a Subscription to another Offer and prorates the current period. | [Billing Specialist](/agents/finance/billing-specialist) | [`Subscription.switched`](/business/events/Subscription.switched) | Two-way: `try`, `send`, `do` | | [Subscription.unsubscribe](/business/nouns/subscription/unsubscribe) | Unsubscribe ends a Subscription at the close of its current period, and the Customer keeps access until then. | [Billing Specialist](/agents/finance/billing-specialist) | [`Subscription.unsubscribed`](/business/events/Subscription.unsubscribed) | Two-way: `try`, `send`, `do` | | [Subscription.create](/business/nouns/subscription/create) | Creates a Subscription. Inherited from [Noun](/business/nouns/noun). | None. | `Subscription.created` | Two-way: `try`, `send`, `do` | | [Subscription.get](/business/nouns/subscription/get) | Returns one Subscription by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Subscription.list](/business/nouns/subscription/list) | Returns Subscriptions, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Subscription.update](/business/nouns/subscription/update) | Changes the given properties of a Subscription. Inherited from [Noun](/business/nouns/noun). | None. | `Subscription.updated` | Two-way: `try`, `send`, `do` | ## Events Events no Verb emits. Each Verb’s Event is in the Verbs table above; every Event is delivered in the same shape. ### Subscription.pastDue A Subscription moved to `pastDue` because its renewal Invoice went overdue. Raised by a state change. | Field | Type | Required | Description | | --- | --- | --- | --- | | `name` | `string` | Yes | `Subscription.pastDue`. | | `at` | `datetime` | Yes | When it happened. | | `seq` | `integer` | No | Its position in the namespace, one more than the Event before; any seq is a cursor into the history. | | `data` | `json` | Yes | The Thing as the Action left it. | | `data.subscription` | [Subscription](/business/nouns/subscription) | Yes | The Subscription as the change left it. | | `data.subscription.status` | `string` | Yes | One of `active`, `trialing`, `pastDue`, `paused`, `incomplete`, or `canceled`. | | `data.subscription.renewsAt` | `datetime` | No | When it next renews. | | `data.subscription.quantity` | `integer` | No | How many units of the Offer’s Price it holds, such as 12 members; 1 by default. | | `data.subscription.trialEndsAt` | `datetime` | No | When a trial ends and the first paid period starts. | | `data.subscription.termEndsAt` | `datetime` | No | When a committed term ends; the Renewal and the renewal notice read it. | | `data.invoice` | [Invoice](/business/nouns/invoice) | Yes | The overdue renewal Invoice. | | `data.previous.status` | `string` | Yes | The `status` before this Event: `active`. | ```json { "$id": "https://api.sb/routewise.dev/events/event_1", "$type": "Event", "name": "Subscription.pastDue", "at": "2026-10-22T12:00:00Z", "data": { "subscription": { "$id": "https://api.sb/routewise.dev/subscriptions/subscription_1", "$type": "Subscription", "status": "pastDue", "renewsAt": "2026-10-22T12:00:00Z", "quantity": 1, "trialEndsAt": "2026-10-22T12:00:00Z", "termEndsAt": "2026-10-22T12:00:00Z" }, "invoice": { "$id": "https://api.sb/routewise.dev/invoices/invoice_1", "$type": "Invoice", "total": { "amount": 25, "currency": "USD" }, "due": "2026-10-22" }, "previous": { "status": "active" } }, "seq": 1 } ``` ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Subscription.create` | Yes | Yes | Yes | No | | `Subscription.get` | Yes | Yes | Yes | Yes | | `Subscription.list` | Yes | Yes | Yes | Yes | | `Subscription.update` | Yes | Yes | Yes | No | | `Subscription.keep` | Yes | Yes | Yes | No | | `Subscription.pause` | Yes | Yes | Yes | No | | `Subscription.renew` | Yes | Yes | Yes | No | | `Subscription.resize` | Yes | Yes | Yes | No | | `Subscription.resume` | Yes | Yes | Yes | No | | `Subscription.switch` | Yes | Yes | Yes | No | | `Subscription.unsubscribe` | Yes | Yes | Yes | No | ## Stripe **Subscription** (`subscription`). The source of truth is db.sb, and Stripe holds a copy written from it. | Property | Stripe field | Source of truth | | --- | --- | --- | | `status` | `status` | Stripe | | `renewsAt` | `items.data[].current_period_end` | Stripe | | `quantity` | `items.data[].quantity` | db.sb | | `trialEndsAt` | `trial_end` | db.sb | | State | Stripe status | | --- | --- | | `incomplete` | `incomplete` | | `trialing` | `trialing` | | `active` | `active` | | `pastDue` | `past_due` | | `paused` | `paused` | | `canceled` | `canceled` | ## Call it **Ask** ```text Renew the latest subscription. ``` **API** ```bash curl -X POST https://api.sb/tutorloop.com/subscriptions/subscription_1/renew \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/tutorloop.com", "invoice": { "$id": "https://api.sb/tutorloop.com/invoices/invoice_1", "$type": "Invoice", "total": { "amount": 60, "currency": "USD" }, "due": "2026-10-22" }, "subscription": { "$id": "https://api.sb/tutorloop.com/subscriptions/subscription_1", "$type": "Subscription", "status": "active" }, "action": { "$id": "https://api.sb/tutorloop.com/actions/action_1", "operation": "Subscription.renew", "status": "done" }, "links": { "self": "https://api.sb/tutorloop.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { invoice, subscription } = await $.Subscription.renew({ subscription: 'subscription_1' }) ``` **CLI** ```bash npx startup-builder do Subscription.renew --json '{"subscription":"subscription_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Subscription.renew({ subscription: 'subscription_1' })" } } ``` ## Example A dental office's Subscription to the $99 monthly reminders [Offer](/business/nouns/offer) renews on the 1st and bills one [Invoice](/business/nouns/invoice) each month until the office unsubscribes. # keep URL: /business/nouns/subscription/keep · Id: `verb:Subscription.keep` · Call: `await $.Subscription.keep({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Keep takes back a cancel before the period closes, so the Subscription renews on its date at the same terms. Keep takes back a cancel before the period closes, so the [Subscription](/business/nouns/subscription) renews on its date at the same terms. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `subscription` | [Subscription](/business/nouns/subscription) | Yes | The ending Subscription. | | `offer` | [Offer](/business/nouns/offer) | No | The Offer to renew on, when the Customer took the save offer. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `subscription` | [Subscription](/business/nouns/subscription) | Yes | The Subscription, active again. | ## Effects - Emits [`Subscription.kept`](/business/events/Subscription.kept). - Performed by the [Billing Specialist](/agents/finance/billing-specialist). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Restores renewal on the original date. - Moves to the named Offer at the next period, when one is given. - Refuses once the period has closed; a canceled Subscription starts again as a new one. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Subscription.keep](/business/nouns/subscription/keep) | | Once the period has closed; a canceled Subscription starts again as a new one | [`refused`](/code/api/errors/refused) | Clear what the check names, then call it again. | [Subscription.keep](/business/nouns/subscription/keep) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Keep the latest subscription. ``` **API** ```bash curl -X POST https://api.sb/tutorloop.com/subscriptions/subscription_1/keep \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/tutorloop.com", "subscription": { "$id": "https://api.sb/tutorloop.com/subscriptions/subscription_1", "$type": "Subscription", "status": "active" }, "action": { "$id": "https://api.sb/tutorloop.com/actions/action_1", "operation": "Subscription.keep", "status": "done" }, "links": { "self": "https://api.sb/tutorloop.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const subscription = await $.Subscription.keep({ subscription: 'subscription_1' }) ``` **CLI** ```bash npx startup-builder do Subscription.keep --json '{"subscription":"subscription_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Subscription.keep({ subscription: 'subscription_1' })" } } ``` # pause URL: /business/nouns/subscription/pause · Id: `verb:Subscription.pause` · Call: `await $.Subscription.pause({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Pause stops billing and Entitlements on a Subscription until a date, without ending it. Pause stops billing and [Entitlements](/business/nouns/entitlement) on a [Subscription](/business/nouns/subscription) until a date, without ending it. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `subscription` | [Subscription](/business/nouns/subscription) | Yes | The active Subscription. | | `until` | `date` | Yes | When billing resumes on its own. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `subscription` | [Subscription](/business/nouns/subscription) | Yes | The paused Subscription. | ## Effects - Emits [`Subscription.paused`](/business/events/Subscription.paused). - Performed by the [Billing Specialist](/agents/finance/billing-specialist). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Moves the next renewal and the term end by the paused days. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Subscription.pause](/business/nouns/subscription/pause) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Pause the latest subscription. ``` **API** ```bash curl -X POST https://api.sb/patentpad.com/subscriptions/subscription_1/pause \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"until":"2026-10-22"}' ``` ```json { "api": "https://api.sb/patentpad.com", "subscription": { "$id": "https://api.sb/patentpad.com/subscriptions/subscription_1", "$type": "Subscription", "status": "paused" }, "action": { "$id": "https://api.sb/patentpad.com/actions/action_1", "operation": "Subscription.pause", "status": "done" }, "links": { "self": "https://api.sb/patentpad.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const subscription = await $.Subscription.pause({ subscription: 'subscription_1', until: '2026-10-22' }) ``` **CLI** ```bash npx startup-builder do Subscription.pause --json '{"subscription":"subscription_1","until":"2026-10-22"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Subscription.pause({ subscription: 'subscription_1', until: '2026-10-22' })" } } ``` # renew URL: /business/nouns/subscription/renew · Id: `verb:Subscription.renew` · Call: `await $.Subscription.renew({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Renew starts a Subscription’s next period and bills it at the Offer Version the Customer accepted. Renew starts a [Subscription](/business/nouns/subscription)’s next period and bills it at the [Offer](/business/nouns/offer) [Version](/business/nouns/version) the [Customer](/business/nouns/customer) accepted. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `subscription` | [Subscription](/business/nouns/subscription) | Yes | The Subscription to renew. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `invoice` | [Invoice](/business/nouns/invoice) | Yes | The Invoice for the new period. | | `subscription` | [Subscription](/business/nouns/subscription) | Yes | The Subscription in its new period. | ## Effects - Emits [`Subscription.renewed`](/business/events/Subscription.renewed). - Performed by the [Billing Specialist](/agents/finance/billing-specialist). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Runs on the period boundary with no caller. - Suspends Entitlements when payment fails after every retry. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The operation is part of an Offer the caller has not accepted or paid for. | [`payment-required`](/code/api/errors/payment-required) | Accept the Offer named in the response, then retry the call. | [Offer.accept](/business/nouns/offer/accept) | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Subscription.renew](/business/nouns/subscription/renew) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Renew the latest subscription. ``` **API** ```bash curl -X POST https://api.sb/tutorloop.com/subscriptions/subscription_1/renew \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/tutorloop.com", "invoice": { "$id": "https://api.sb/tutorloop.com/invoices/invoice_1", "$type": "Invoice", "total": { "amount": 60, "currency": "USD" }, "due": "2026-10-22" }, "subscription": { "$id": "https://api.sb/tutorloop.com/subscriptions/subscription_1", "$type": "Subscription", "status": "active" }, "action": { "$id": "https://api.sb/tutorloop.com/actions/action_1", "operation": "Subscription.renew", "status": "done" }, "links": { "self": "https://api.sb/tutorloop.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { invoice, subscription } = await $.Subscription.renew({ subscription: 'subscription_1' }) ``` **CLI** ```bash npx startup-builder do Subscription.renew --json '{"subscription":"subscription_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Subscription.renew({ subscription: 'subscription_1' })" } } ``` # resize URL: /business/nouns/subscription/resize · Id: `verb:Subscription.resize` · Call: `await $.Subscription.resize({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Resize changes how many units a Subscription holds and prorates the current period. Resize changes how many units a [Subscription](/business/nouns/subscription) holds and prorates the current period. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `subscription` | [Subscription](/business/nouns/subscription) | Yes | The Subscription to change. | | `quantity` | `integer` | Yes | The new unit count. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `subscription` | [Subscription](/business/nouns/subscription) | Yes | The Subscription at its new quantity. | ## Effects - Emits [`Subscription.resized`](/business/events/Subscription.resized). - Performed by the [Billing Specialist](/agents/finance/billing-specialist). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Bills or credits the prorated difference at once. - A lower quantity takes effect at the next period. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Subscription.resize](/business/nouns/subscription/resize) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Resize the latest subscription. ``` **API** ```bash curl -X POST https://api.sb/ledgerlark.com/subscriptions/subscription_1/resize \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"quantity":1}' ``` ```json { "api": "https://api.sb/ledgerlark.com", "subscription": { "$id": "https://api.sb/ledgerlark.com/subscriptions/subscription_1", "$type": "Subscription", "status": "active" }, "action": { "$id": "https://api.sb/ledgerlark.com/actions/action_1", "operation": "Subscription.resize", "status": "done" }, "links": { "self": "https://api.sb/ledgerlark.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const subscription = await $.Subscription.resize({ subscription: 'subscription_1', quantity: 1 }) ``` **CLI** ```bash npx startup-builder do Subscription.resize --json '{"subscription":"subscription_1","quantity":1}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Subscription.resize({ subscription: 'subscription_1', quantity: 1 })" } } ``` # resume URL: /business/nouns/subscription/resume · Id: `verb:Subscription.resume` · Call: `await $.Subscription.resume({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Resume restarts billing and Entitlements on a paused Subscription before its pause ends. Resume restarts billing and [Entitlements](/business/nouns/entitlement) on a paused [Subscription](/business/nouns/subscription) before its pause ends. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `subscription` | [Subscription](/business/nouns/subscription) | Yes | The paused Subscription. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `subscription` | [Subscription](/business/nouns/subscription) | Yes | The active Subscription. | ## Effects - Emits [`Subscription.resumed`](/business/events/Subscription.resumed). - Performed by the [Billing Specialist](/agents/finance/billing-specialist). - Two-way: it runs at once, in the `try`, `send` and `do` modes. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Subscription.resume](/business/nouns/subscription/resume) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Resume the latest subscription. ``` **API** ```bash curl -X POST https://api.sb/kilnbakery.com/subscriptions/subscription_1/resume \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/kilnbakery.com", "subscription": { "$id": "https://api.sb/kilnbakery.com/subscriptions/subscription_1", "$type": "Subscription", "status": "active" }, "action": { "$id": "https://api.sb/kilnbakery.com/actions/action_1", "operation": "Subscription.resume", "status": "done" }, "links": { "self": "https://api.sb/kilnbakery.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const subscription = await $.Subscription.resume({ subscription: 'subscription_1' }) ``` **CLI** ```bash npx startup-builder do Subscription.resume --json '{"subscription":"subscription_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Subscription.resume({ subscription: 'subscription_1' })" } } ``` # switch URL: /business/nouns/subscription/switch · Id: `verb:Subscription.switch` · Call: `await $.Subscription.switch({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Switch moves a Subscription to another Offer and prorates the current period. Switch moves a [Subscription](/business/nouns/subscription) to another [Offer](/business/nouns/offer) and prorates the current period. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `subscription` | [Subscription](/business/nouns/subscription) | Yes | The Subscription to move. | | `offer` | [Offer](/business/nouns/offer) | Yes | The Offer to move to. | | `effectiveAt` | `datetime` | No | When the move takes effect; moving existing Customers to a higher Price waits at least the notice period. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `subscription` | [Subscription](/business/nouns/subscription) | Yes | The Subscription on its new Offer. | ## Effects - Emits [`Subscription.switched`](/business/events/Subscription.switched). - Performed by the [Billing Specialist](/agents/finance/billing-specialist). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Bills or credits the prorated difference at once. - Moving existing Customers to a higher Price sends notice and switches each at its first renewal after the notice period. - A move to a cheaper Offer runs at once, with no Limit, Approval or delay window. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The input does not match the schema of the operation. | [`invalid-input`](/code/api/errors/invalid-input) | Read the schema of the operation, then send every required field with the right type. | [Subscription.switch](/business/nouns/subscription/switch) | | The operation is part of an Offer the caller has not accepted or paid for. | [`payment-required`](/code/api/errors/payment-required) | Accept the Offer named in the response, then retry the call. | [Offer.accept](/business/nouns/offer/accept) | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Subscription.switch](/business/nouns/subscription/switch) | | The record is not in a state that allows this Verb, so the call is refused. | [`refused`](/code/api/errors/refused) | Read the record, run the Verb that moves it to an allowed state, then retry. | [Subscription.switch](/business/nouns/subscription/switch) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Switch the latest subscription with an offer. ``` **API** ```bash curl -X POST https://api.sb/shiftnote.app/subscriptions/subscription_1/switch \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"offer":"offer_1"}' ``` ```json { "api": "https://api.sb/shiftnote.app", "subscription": { "$id": "https://api.sb/shiftnote.app/subscriptions/subscription_1", "$type": "Subscription", "status": "active" }, "action": { "$id": "https://api.sb/shiftnote.app/actions/action_1", "operation": "Subscription.switch", "status": "done" }, "links": { "self": "https://api.sb/shiftnote.app/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const subscription = await $.Subscription.switch({ subscription: 'subscription_1', offer: 'offer_1' }) ``` **CLI** ```bash npx startup-builder do Subscription.switch --json '{"subscription":"subscription_1","offer":"offer_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Subscription.switch({ subscription: 'subscription_1', offer: 'offer_1' })" } } ``` # unsubscribe URL: /business/nouns/subscription/unsubscribe · Id: `verb:Subscription.unsubscribe` · Call: `await $.Subscription.unsubscribe({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Unsubscribe ends a Subscription at the close of its current period, and the Customer keeps access until then. Unsubscribe ends a [Subscription](/business/nouns/subscription) at the close of its current period, and the [Customer](/business/nouns/customer) keeps access until then. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `subscription` | [Subscription](/business/nouns/subscription) | Yes | The Subscription to end. | | `reason` | `text` | No | Why the Customer leaves. | | `comment` | `text` | No | The Customer’s own words, kept verbatim as the Evidence quote. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `subscription` | [Subscription](/business/nouns/subscription) | Yes | The Subscription, ending. | ## Effects - Emits [`Subscription.unsubscribed`](/business/events/Subscription.unsubscribed). - Performed by the [Billing Specialist](/agents/finance/billing-specialist). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Stops renewal. - Keeps the Customer: a Customer is a Customer forever. - Runs at once: no Limit, Approval or delay window stands between the Customer and the result. - Records Behavior-grade Evidence that refutes the slot its reason code tests; the stated reason alone binds as Opinion. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Subscription.unsubscribe](/business/nouns/subscription/unsubscribe) | | The record is not in a state that allows this Verb, so the call is refused. | [`refused`](/code/api/errors/refused) | Read the record, run the Verb that moves it to an allowed state, then retry. | [Subscription.unsubscribe](/business/nouns/subscription/unsubscribe) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Unsubscribe the latest subscription. ``` **API** ```bash curl -X POST https://api.sb/tutorloop.com/subscriptions/subscription_1/unsubscribe \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/tutorloop.com", "subscription": { "$id": "https://api.sb/tutorloop.com/subscriptions/subscription_1", "$type": "Subscription", "status": "active" }, "action": { "$id": "https://api.sb/tutorloop.com/actions/action_1", "operation": "Subscription.unsubscribe", "status": "done" }, "links": { "self": "https://api.sb/tutorloop.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const subscription = await $.Subscription.unsubscribe({ subscription: 'subscription_1' }) ``` **CLI** ```bash npx startup-builder do Subscription.unsubscribe --json '{"subscription":"subscription_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Subscription.unsubscribe({ subscription: 'subscription_1' })" } } ``` Guides that call it: [Cancel a customer’s subscription](/products/offers/cancel-a-subscription). # Supplier URL: /business/nouns/supplier · Id: `noun:supplier` > A Supplier is a Person or Company that delivers work through a Startup’s human supply: recruited, credentialed, and paid out. A Supplier is a [Person](/business/nouns/person) or [Company](/business/nouns/company) that delivers work through a [Startup](/business/nouns/startup)’s human supply: recruited, credentialed, and paid out. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `status` | `string` | Yes | One of `recruited`, `onboarded`, `active`, or `suspended`. | | `payoutAccount` | `string` | No | Where payouts land, held through Stripe. |
Inherited from [Party](/business/nouns/party): 1 property | Property | Type | Required | Description | | --- | --- | --- | --- | | `name` | `string` | Yes | The legal or personal name. |
## Object ```json { "$id": "https://api.sb/kilnbakery.com/suppliers/supplier_1", "$type": "Supplier", "name": "Kiln Bakery", "status": "recruited", "payoutAccount": "Example payout account" } ``` ## Relationships - A Supplier **delivers** many [Services](/business/nouns/service): Suppliers staff [Services](/business/nouns/service) through the [Startup](/business/nouns/startup)’s human supply. `delivers`, inverse [`suppliedBy`](/business/nouns/service#rel-supplied-by). - A Supplier **holds** many [Credentials](/business/nouns/credential): the [Credentials](/business/nouns/credential) a Supplier holds decide which [Reserved Acts](/business/nouns/reserved-act) it may perform; standing is read fresh on every use. `holds`, inverse [`heldBySupplier`](/business/nouns/credential#rel-held-by-supplier). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Supplier.create](/business/nouns/supplier/create) | Creates a Supplier. Inherited from [Noun](/business/nouns/noun). | None. | `Supplier.created` | Two-way: `try`, `send`, `do` | | [Supplier.get](/business/nouns/supplier/get) | Returns one Supplier by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Supplier.list](/business/nouns/supplier/list) | Returns Suppliers, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Supplier.update](/business/nouns/supplier/update) | Changes the given properties of a Supplier. Inherited from [Noun](/business/nouns/noun). | None. | `Supplier.updated` | Two-way: `try`, `send`, `do` | | [Supplier.delete](/business/nouns/supplier/delete) | Deletes a Supplier; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Supplier.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Supplier.create` | Yes | Yes | Yes | No | | `Supplier.get` | Yes | Yes | Yes | Yes | | `Supplier.list` | Yes | Yes | Yes | Yes | | `Supplier.update` | Yes | Yes | Yes | No | | `Supplier.delete` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Add a supplier to PetPantry. ``` **API** ```bash curl -X POST https://api.sb/petpantry.shop/suppliers \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"name":"PetPantry"}' ``` ```json { "api": "https://api.sb/petpantry.shop", "supplier": { "$id": "https://api.sb/petpantry.shop/suppliers/supplier_1", "$type": "Supplier", "name": "PetPantry", "status": "recruited" }, "action": { "$id": "https://api.sb/petpantry.shop/actions/action_1", "operation": "Supplier.create", "status": "done" }, "links": { "self": "https://api.sb/petpantry.shop/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const supplier = await $.Supplier.create({ name: 'PetPantry' }) ``` **CLI** ```bash npx startup-builder do Supplier.create --json '{"name":"PetPantry"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Supplier.create({ name: 'PetPantry' })" } } ``` ## Example A licensed home inspector recruited by an inspection-booking network is a Supplier. She holds her state [Credential](/business/nouns/credential), takes assigned bookings, and is paid out to her `payoutAccount` after each accepted report. # Suppression URL: /business/nouns/suppression · Id: `noun:suppression` > A Suppression is an address a Company never sends commercial Messages to, read before every send from any of its Startups. A Suppression is an address a [Company](/business/nouns/company) never sends commercial [Messages](/business/nouns/message) to, read before every send from any of its [Startups](/business/nouns/startup). ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `address` | `string` | Yes | The email address or phone number. | | `reason` | `string` | No | Why it is suppressed, such as an opt-out or a bounce. | ## Object ```json { "$id": "https://api.sb/patentpad.com/suppressions/suppression_1", "$type": "Suppression", "address": "Example address", "reason": "Example reason" } ``` ## Relationships - A Suppression **is kept by** one [Company](/business/nouns/company): a [Company](/business/nouns/company)’s Suppressions bind every [Startup](/business/nouns/startup) it holds: no commercial [Message](/business/nouns/message) goes to a suppressed address. `keptBy`, inverse [`keeps`](/business/nouns/company#rel-keeps). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Suppression.create](/business/nouns/suppression/create) | Creates a Suppression. Inherited from [Noun](/business/nouns/noun). | None. | `Suppression.created` | Two-way: `try`, `send`, `do` | | [Suppression.get](/business/nouns/suppression/get) | Returns one Suppression by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Suppression.list](/business/nouns/suppression/list) | Returns Suppressions, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | A Suppression is kept forever and never edited: it has no `update` or `delete`. ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Suppression.create` | Yes | Yes | Yes | No | | `Suppression.get` | Yes | Yes | Yes | Yes | | `Suppression.list` | Yes | Yes | Yes | Yes | ## Call it **Ask** ```text Add a suppression to ShiftNote. ``` **API** ```bash curl -X POST https://api.sb/shiftnote.app/suppressions \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"address":"Example address"}' ``` ```json { "api": "https://api.sb/shiftnote.app", "suppression": { "$id": "https://api.sb/shiftnote.app/suppressions/suppression_1", "$type": "Suppression", "address": "Example address" }, "action": { "$id": "https://api.sb/shiftnote.app/actions/action_1", "operation": "Suppression.create", "status": "done" }, "links": { "self": "https://api.sb/shiftnote.app/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const suppression = await $.Suppression.create({ address: 'Example address' }) ``` **CLI** ```bash npx startup-builder do Suppression.create --json '{"address":"Example address"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Suppression.create({ address: 'Example address' })" } } ``` ## Example A florist unsubscribes from one sibling's newsletter. The Suppression, kept by their [Company](/business/nouns/company), stops commercial Messages to her from every Startup it holds, with `reason: unsubscribed`. # Survey URL: /business/nouns/survey · Id: `noun:survey` > A Survey is a Form sent to measure, such as NPS or CSAT, whose answers become Metrics and Evidence. A Survey is a [Form](/business/nouns/form) sent to measure, such as NPS or CSAT, whose answers become [Metrics](/business/nouns/metric) and [Evidence](/business/nouns/evidence). ## Properties
Inherited from [Form](/business/nouns/form): 1 property | Property | Type | Required | Description | | --- | --- | --- | --- | | `fields` | `json` | Yes | The fields and their types. |
## Object ```json { "$id": "https://api.sb/quietcopy.com/surveys/survey_1", "$type": "Survey", "fields": {} } ``` ## Relationships - A Survey **informs** many [Metrics](/business/nouns/metric): Survey answers compute [Metrics](/business/nouns/metric), such as a satisfaction score. `informs`, inverse [`informedBy`](/business/nouns/metric#rel-informed-by). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Survey.create](/business/nouns/survey/create) | Creates a Survey. Inherited from [Noun](/business/nouns/noun). | None. | `Survey.created` | Two-way: `try`, `send`, `do` | | [Survey.get](/business/nouns/survey/get) | Returns one Survey by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Survey.list](/business/nouns/survey/list) | Returns Surveys, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Survey.update](/business/nouns/survey/update) | Changes the given properties of a Survey. Inherited from [Noun](/business/nouns/noun). | None. | `Survey.updated` | Two-way: `try`, `send`, `do` | | [Survey.delete](/business/nouns/survey/delete) | Deletes a Survey; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Survey.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Survey.create` | Yes | Yes | Yes | No | | `Survey.get` | Yes | Yes | Yes | Yes | | `Survey.list` | Yes | Yes | Yes | Yes | | `Survey.update` | Yes | Yes | Yes | No | | `Survey.delete` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Add a survey to TutorLoop. ``` **API** ```bash curl -X POST https://api.sb/tutorloop.com/surveys \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"fields":{}}' ``` ```json { "api": "https://api.sb/tutorloop.com", "survey": { "$id": "https://api.sb/tutorloop.com/surveys/survey_1", "$type": "Survey", "fields": {} }, "action": { "$id": "https://api.sb/tutorloop.com/actions/action_1", "operation": "Survey.create", "status": "done" }, "links": { "self": "https://api.sb/tutorloop.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const survey = await $.Survey.create({ fields: {} }) ``` **CLI** ```bash npx startup-builder do Survey.create --json '{"fields":{}}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Survey.create({ fields: {} })" } } ``` ## Example An NPS Survey goes to each [Customer](/business/nouns/customer) 30 days after signup. Scores feed the NPS Metric, and comments become Evidence. # System URL: /business/nouns/system · Id: `noun:system` > A System is the headless software for one job, such as CRM or billing, that every Startup runs on shared data. A System is the headless software for one job, such as CRM or billing, that every [Startup](/business/nouns/startup) runs on shared data. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `job` | `string` | Yes | The one job it does. | ## Object ```json { "$id": "https://api.sb/routewise.dev/systems/system_1", "$type": "System", "job": "Example job" } ``` ## Relationships - A System **is connected via** many [Integrations](/business/nouns/integration): an [Integration](/business/nouns/integration) connects an outside [Source](/business/nouns/source) to one System, with credentials at [Studio](/business/nouns/studio), [Startup](/business/nouns/startup) or [Customer](/business/nouns/customer) scope. `connectedVia`, inverse [`connects`](/business/nouns/integration#rel-connects). - A System **defines** many [Nouns](/business/nouns/noun): the [Nouns](/business/nouns/noun) a System keeps records of; several Systems can share one Noun. `defines`, inverse [`definedIn`](/business/nouns/noun#rel-defined-in). - A System **is packaged as** many [Software Products](/business/nouns/software): [Software](/business/nouns/software) ships Systems to its [Customers](/business/nouns/customer) as one [Product](/business/nouns/product), headless or with an [App](/business/nouns/app). `packagedAs`, inverse [`packages`](/business/nouns/software#rel-packages). - A System **is run by** many [Startups](/business/nouns/startup): a [Startup](/business/nouns/startup) runs its work on headless Systems, such as CRM or billing, that every Startup shares. `runBy`, inverse [`runs`](/business/nouns/startup#rel-runs). - A System **runs on** many [Capabilities](/business/nouns/capability): a System is built on [Capabilities](/business/nouns/capability), such as [Workflows](/business/nouns/workflow) or Search, that every [Startup](/business/nouns/startup) reaches with one key. `runsOn`, inverse [`runs`](/business/nouns/capability#rel-runs). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [System.create](/business/nouns/system/create) | Creates a System. Inherited from [Noun](/business/nouns/noun). | None. | `System.created` | Two-way: `try`, `send`, `do` | | [System.get](/business/nouns/system/get) | Returns one System by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [System.list](/business/nouns/system/list) | Returns Systems, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [System.update](/business/nouns/system/update) | Changes the given properties of a System. Inherited from [Noun](/business/nouns/noun). | None. | `System.updated` | Two-way: `try`, `send`, `do` | | [System.delete](/business/nouns/system/delete) | Deletes a System; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `System.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `System.create` | Yes | Yes | Yes | No | | `System.get` | Yes | Yes | Yes | Yes | | `System.list` | Yes | Yes | Yes | Yes | | `System.update` | Yes | Yes | Yes | No | | `System.delete` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Add a system to LedgerLark. ``` **API** ```bash curl -X POST https://api.sb/ledgerlark.com/systems \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"job":"Example job"}' ``` ```json { "api": "https://api.sb/ledgerlark.com", "system": { "$id": "https://api.sb/ledgerlark.com/systems/system_1", "$type": "System", "job": "Example job" }, "action": { "$id": "https://api.sb/ledgerlark.com/actions/action_1", "operation": "System.create", "status": "done" }, "links": { "self": "https://api.sb/ledgerlark.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const system = await $.System.create({ job: 'Example job' }) ``` **CLI** ```bash npx startup-builder do System.create --json '{"job":"Example job"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.System.create({ job: 'Example job' })" } } ``` ## Example The CRM System holds [Contacts](/business/nouns/contact), [Deals](/business/nouns/deal), and [Quotes](/business/nouns/quote) for every Startup in the [Studio](/business/nouns/studio), each Startup seeing only its own. # assign URL: /business/nouns/task/assign · Id: `verb:Task.assign` · Call: `await $.Task.assign({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Assign gives a Task to a Worker, human or agent, and places it in that Worker’s worklist. Assign gives a [Task](/business/nouns/task) to a [Worker](/business/nouns/worker), human or agent, and places it in that Worker’s worklist. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `task` | [Task](/business/nouns/task) | Yes | The Task to assign. | | `worker` | [Worker](/business/nouns/worker) | Yes | The Worker who takes it. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `task` | [Task](/business/nouns/task) | Yes | The assigned Task. | ## Effects - Emits [`Task.assigned`](/business/events/Task.assigned). - Performed by the [Product Lead](/agents/product/product-lead). - Moves the waiting Action from `awaitingWorker` to `awaitingAction`. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Task.assign](/business/nouns/task/assign) | | The record is not in a state that allows this Verb, so the call is refused. | [`refused`](/code/api/errors/refused) | Read the record, run the Verb that moves it to an allowed state, then retry. | [Task.assign](/business/nouns/task/assign) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Assign the latest task with a worker. ``` **API** ```bash curl -X POST https://api.sb/quietcopy.com/tasks/task_1/assign \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"worker":"worker_1"}' ``` ```json { "api": "https://api.sb/quietcopy.com", "task": { "$id": "https://api.sb/quietcopy.com/tasks/task_1", "$type": "Task", "status": "pending", "mode": "try" }, "action": { "$id": "https://api.sb/quietcopy.com/actions/action_1", "operation": "Task.assign", "status": "done" }, "links": { "self": "https://api.sb/quietcopy.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const task = await $.Task.assign({ task: 'task_1', worker: 'worker_1' }) ``` **CLI** ```bash npx startup-builder do Task.assign --json '{"task":"task_1","worker":"worker_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Task.assign({ task: 'task_1', worker: 'worker_1' })" } } ``` # claim URL: /business/nouns/task/claim · Id: `verb:Task.claim` · Call: `await $.Task.claim({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Claim takes an offered Task from a shared queue or a handoff and makes the calling Worker its assignee. Claim takes an offered [Task](/business/nouns/task) from a shared queue or a handoff and makes the calling [Worker](/business/nouns/worker) its assignee. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `task` | [Task](/business/nouns/task) | Yes | The offered Task. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `task` | [Task](/business/nouns/task) | Yes | The Task, assigned to the caller. | ## Effects - Emits [`Task.claimed`](/business/events/Task.claimed). - Performed by the [Supply Manager](/agents/operations/supply-manager). - Removes the Task from every other Worker’s queue. - Releases the claim if the Task sits untouched past its claim window. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Task.claim](/business/nouns/task/claim) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Claim the latest task. ``` **API** ```bash curl -X POST https://api.sb/ledgerlark.com/tasks/task_1/claim \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/ledgerlark.com", "task": { "$id": "https://api.sb/ledgerlark.com/tasks/task_1", "$type": "Task", "status": "pending", "mode": "try" }, "action": { "$id": "https://api.sb/ledgerlark.com/actions/action_1", "operation": "Task.claim", "status": "done" }, "links": { "self": "https://api.sb/ledgerlark.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const task = await $.Task.claim({ task: 'task_1' }) ``` **CLI** ```bash npx startup-builder do Task.claim --json '{"task":"task_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Task.claim({ task: 'task_1' })" } } ``` # complete URL: /business/nouns/task/complete · Id: `verb:Task.complete` · Call: `await $.Task.complete({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Complete marks a Task done and resumes the Action that waited on it. Complete marks a [Task](/business/nouns/task) done and resumes the [Action](/business/nouns/action) that waited on it. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `task` | [Task](/business/nouns/task) | Yes | The assigned Task. | | `result` | `json` | No | What the Worker produced. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `task` | [Task](/business/nouns/task) | Yes | The completed Task. | ## Effects - Emits [`Task.completed`](/business/events/Task.completed). - Performed by the [Supply Manager](/agents/operations/supply-manager). ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The input does not match the schema of the operation. | [`invalid-input`](/code/api/errors/invalid-input) | Read the schema of the operation, then send every required field with the right type. | [Task.complete](/business/nouns/task/complete) | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Task.complete](/business/nouns/task/complete) | | The record is not in a state that allows this Verb, so the call is refused. | [`refused`](/code/api/errors/refused) | Read the record, run the Verb that moves it to an allowed state, then retry. | [Task.complete](/business/nouns/task/complete) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Complete the latest task. ``` **API** ```bash curl -X POST https://api.sb/petpantry.shop/tasks/task_1/complete \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/petpantry.shop", "task": { "$id": "https://api.sb/petpantry.shop/tasks/task_1", "$type": "Task", "status": "pending", "mode": "try" }, "action": { "$id": "https://api.sb/petpantry.shop/actions/action_1", "operation": "Task.complete", "status": "done" }, "links": { "self": "https://api.sb/petpantry.shop/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const task = await $.Task.complete({ task: 'task_1' }) ``` **CLI** ```bash npx startup-builder do Task.complete --json '{"task":"task_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Task.complete({ task: 'task_1' })" } } ``` # delegate URL: /business/nouns/task/delegate · Id: `verb:Task.delegate` · Call: `await $.Task.delegate({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Delegate passes a Task to another Role along a declared handoff and keeps its history. Delegate passes a [Task](/business/nouns/task) to another [Role](/business/nouns/role) along a declared handoff and keeps its history. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `task` | [Task](/business/nouns/task) | Yes | The Task to pass on. | | `role` | [Role](/business/nouns/role) | Yes | The Role that receives it. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `task` | [Task](/business/nouns/task) | Yes | The Task, held by the new Role. | ## Effects - Emits [`Task.delegated`](/business/events/Task.delegated). - Performed by the [Operations Lead](/agents/operations/operations-lead). ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Task.delegate](/business/nouns/task/delegate) | | The record is not in a state that allows this Verb, so the call is refused. | [`refused`](/code/api/errors/refused) | Read the record, run the Verb that moves it to an allowed state, then retry. | [Task.delegate](/business/nouns/task/delegate) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Delegate the latest task with a role. ``` **API** ```bash curl -X POST https://api.sb/kilnbakery.com/tasks/task_1/delegate \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"role":"role_1"}' ``` ```json { "api": "https://api.sb/kilnbakery.com", "task": { "$id": "https://api.sb/kilnbakery.com/tasks/task_1", "$type": "Task", "status": "pending", "mode": "try" }, "action": { "$id": "https://api.sb/kilnbakery.com/actions/action_1", "operation": "Task.delegate", "status": "done" }, "links": { "self": "https://api.sb/kilnbakery.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const task = await $.Task.delegate({ task: 'task_1', role: 'role_1' }) ``` **CLI** ```bash npx startup-builder do Task.delegate --json '{"task":"task_1","role":"role_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Task.delegate({ task: 'task_1', role: 'role_1' })" } } ``` # escalate URL: /business/nouns/task/escalate · Id: `verb:Task.escalate` · Call: `await $.Task.escalate({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Escalate moves a Task to the Role its current Role escalates to, with the reason attached. Escalate moves a [Task](/business/nouns/task) to the [Role](/business/nouns/role) its current Role escalates to, with the reason attached. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `task` | [Task](/business/nouns/task) | Yes | The Task to escalate. | | `reason` | `text` | Yes | Why the current Role cannot finish it. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `task` | [Task](/business/nouns/task) | Yes | The Task, assigned upward. | ## Effects - Emits [`Task.escalated`](/business/events/Task.escalated). - Performed by the [Operations Lead](/agents/operations/operations-lead). - Keeps the Task’s history and due time. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Task.escalate](/business/nouns/task/escalate) | | The record is not in a state that allows this Verb, so the call is refused. | [`refused`](/code/api/errors/refused) | Read the record, run the Verb that moves it to an allowed state, then retry. | [Task.escalate](/business/nouns/task/escalate) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Escalate the latest task. ``` **API** ```bash curl -X POST https://api.sb/shiftnote.app/tasks/task_1/escalate \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"reason":"Example reason"}' ``` ```json { "api": "https://api.sb/shiftnote.app", "task": { "$id": "https://api.sb/shiftnote.app/tasks/task_1", "$type": "Task", "status": "pending", "mode": "try" }, "action": { "$id": "https://api.sb/shiftnote.app/actions/action_1", "operation": "Task.escalate", "status": "done" }, "links": { "self": "https://api.sb/shiftnote.app/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const task = await $.Task.escalate({ task: 'task_1', reason: 'Example reason' }) ``` **CLI** ```bash npx startup-builder do Task.escalate --json '{"task":"task_1","reason":"Example reason"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Task.escalate({ task: 'task_1', reason: 'Example reason' })" } } ``` # Task URL: /business/nouns/task · Id: `noun:task` > A Task is an Action waiting on a Worker, with an assignee, a due time, and a place in that Worker’s inbox. A Task is an [Action](/business/nouns/action) waiting on a [Worker](/business/nouns/worker), with an assignee, a due time, and a place in that Worker’s inbox. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `due` | `datetime` | No | When the Task is due. | | `priority` | `integer` | No | Its rank in the inbox, highest first. | | `recurrence` | `string` | No | The schedule a recurring duty repeats on. |
Inherited from [Action](/business/nouns/action): 11 properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `status` | `string` | Yes | One of `pending`, `done`, `failed`, `canceled`, or `refused`. | | `reason` | `string` | No | Why a pending Action waits: `queued`, `running`, `retrying`, `awaitingWorker`, `awaitingInput`, `awaitingSource`, `awaitingAction`, or `awaitingTime`. | | `mode` | `string` | Yes | How the caller invoked it: `try`, `send`, or `do`. | | `by` | [Worker](/business/nouns/worker) | No | The Worker that performed it. | | `for` | [Party](/business/nouns/party) | No | The Party it was done on behalf of. | | `via` | `string` | No | The Interface or request it arrived through. | | `on` | `string` | No | The Action or Event that caused it, such as the failed attempt a retry follows. | | `thing` | `string` | No | The record, at the Version the Action was decided against. | | `input` | `json` | No | The input it was called with. | | `createdAt` | `datetime` | No | When it was called. | | `reserved` | `money` | No | The most this Action may cost, held against its Limits from the check until it settles, billed misses included. |
## Object ```json { "$id": "https://api.sb/routewise.dev/tasks/task_1", "$type": "Task", "status": "pending", "reason": "queued", "mode": "try", "by": "worker_1", "for": "party_1", "via": "API", "on": "Invoice.overdue", "thing": "invoice_1@v3", "input": {}, "createdAt": "2026-10-22T12:00:00Z", "reserved": { "amount": 25, "currency": "USD" }, "due": "2026-10-22T12:00:00Z", "priority": 1, "recurrence": "Weekly on Friday" } ``` ## Relationships - A Task **is assigned to** one [Worker](/business/nouns/worker): the [Worker](/business/nouns/worker) a Task waits on; the Task sits in that Worker’s inbox until it is done. `assignedTo`, inverse [`tasks`](/business/nouns/worker#rel-tasks). - A Task **has** one [Project](/business/nouns/project): a [Project](/business/nouns/project) is made of Tasks. `project`, inverse [`plans`](/business/nouns/project#rel-plans). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Task.assign](/business/nouns/task/assign) | Assign gives a Task to a Worker, human or agent, and places it in that Worker’s worklist. | [Product Lead](/agents/product/product-lead) | [`Task.assigned`](/business/events/Task.assigned) | None. | | [Task.claim](/business/nouns/task/claim) | Claim takes an offered Task from a shared queue or a handoff and makes the calling Worker its assignee. | [Supply Manager](/agents/operations/supply-manager) | [`Task.claimed`](/business/events/Task.claimed) | None. | | [Task.complete](/business/nouns/task/complete) | Complete marks a Task done and resumes the Action that waited on it. | [Supply Manager](/agents/operations/supply-manager) | [`Task.completed`](/business/events/Task.completed) | None. | | [Task.delegate](/business/nouns/task/delegate) | Delegate passes a Task to another Role along a declared handoff and keeps its history. | [Operations Lead](/agents/operations/operations-lead) | [`Task.delegated`](/business/events/Task.delegated) | None. | | [Task.escalate](/business/nouns/task/escalate) | Escalate moves a Task to the Role its current Role escalates to, with the reason attached. | [Operations Lead](/agents/operations/operations-lead) | [`Task.escalated`](/business/events/Task.escalated) | None. | | [Task.next](/business/nouns/task/next) | Next returns the oldest open Task the calling Worker’s Roles may claim, without claiming it. | [Worker](/business/nouns/worker) | [`Task.offered`](/business/events/Task.offered) | None. | | [Task.return](/business/nouns/task/return) | Return hands an offered Task back to its sender, unchanged, with the reason the receiver cannot take it. | [Supply Manager](/agents/operations/supply-manager) | [`Task.returned`](/business/events/Task.returned) | None. | | [Task.create](/business/nouns/task/create) | Creates a Task. Inherited from [Noun](/business/nouns/noun). | None. | `Task.created` | Two-way: `try`, `send`, `do` | | [Task.get](/business/nouns/task/get) | Returns one Task by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Task.list](/business/nouns/task/list) | Returns Tasks, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Task.update](/business/nouns/task/update) | Changes the given properties of a Task. Inherited from [Noun](/business/nouns/noun). | None. | `Task.updated` | Two-way: `try`, `send`, `do` | | [Task.delete](/business/nouns/task/delete) | Deletes a Task; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Task.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Task.create` | Yes | Yes | Yes | No | | `Task.get` | Yes | Yes | Yes | Yes | | `Task.list` | Yes | Yes | Yes | Yes | | `Task.update` | Yes | Yes | Yes | No | | `Task.delete` | Yes | Yes | Yes | No | | `Task.assign` | Yes | Yes | Yes | No | | `Task.claim` | Yes | Yes | Yes | No | | `Task.complete` | Yes | Yes | Yes | No | | `Task.delegate` | Yes | Yes | Yes | No | | `Task.escalate` | Yes | Yes | Yes | No | | `Task.next` | Yes | Yes | Yes | No | | `Task.return` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Assign the latest task with a worker. ``` **API** ```bash curl -X POST https://api.sb/quietcopy.com/tasks/task_1/assign \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"worker":"worker_1"}' ``` ```json { "api": "https://api.sb/quietcopy.com", "task": { "$id": "https://api.sb/quietcopy.com/tasks/task_1", "$type": "Task", "status": "pending", "mode": "try" }, "action": { "$id": "https://api.sb/quietcopy.com/actions/action_1", "operation": "Task.assign", "status": "done" }, "links": { "self": "https://api.sb/quietcopy.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const task = await $.Task.assign({ task: 'task_1', worker: 'worker_1' }) ``` **CLI** ```bash npx startup-builder do Task.assign --json '{"task":"task_1","worker":"worker_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Task.assign({ task: 'task_1', worker: 'worker_1' })" } } ``` ## Example A parent asks a tutoring marketplace to reschedule. The reply is a Task assigned to the [Customer Lead](/agents/customer/customer-lead), due in 15 minutes, at the top of its inbox. # next URL: /business/nouns/task/next · Id: `verb:Task.next` · Call: `await $.Task.next({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Next returns the oldest open Task the calling Worker’s Roles may claim, without claiming it. Next returns the oldest open [Task](/business/nouns/task) the calling [Worker](/business/nouns/worker)’s [Roles](/business/nouns/role) may claim, without claiming it. ## Inputs None. ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `task` | [Task](/business/nouns/task) | No | The Task to claim next; empty when the queue is drained. | ## Effects - Emits [`Task.offered`](/business/events/Task.offered). ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Task.next](/business/nouns/task/next) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Next the latest task. ``` **API** ```bash curl -X POST https://api.sb/tutorloop.com/tasks/next \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/tutorloop.com", "task": { "$id": "https://api.sb/tutorloop.com/tasks/task_1", "$type": "Task", "status": "pending", "mode": "try" }, "action": { "$id": "https://api.sb/tutorloop.com/actions/action_1", "operation": "Task.next", "status": "done" }, "links": { "self": "https://api.sb/tutorloop.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const task = await $.Task.next() ``` **CLI** ```bash npx startup-builder do Task.next ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Task.next()" } } ``` # return URL: /business/nouns/task/return · Id: `verb:Task.return` · Call: `await $.Task.return({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Return hands an offered Task back to its sender, unchanged, with the reason the receiver cannot take it. Return hands an offered [Task](/business/nouns/task) back to its sender, unchanged, with the reason the receiver cannot take it. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `task` | [Task](/business/nouns/task) | Yes | The Task to hand back. | | `reason` | `text` | Yes | What is missing, or why the Task is outside the receiver’s lane. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `task` | [Task](/business/nouns/task) | Yes | The Task, back with its sender. | ## Effects - Emits [`Task.returned`](/business/events/Task.returned). - Performed by the [Supply Manager](/agents/operations/supply-manager). - Escalates the Task when it is returned a second time. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Task.return](/business/nouns/task/return) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Return the latest task. ``` **API** ```bash curl -X POST https://api.sb/patentpad.com/tasks/task_1/return \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"reason":"Example reason"}' ``` ```json { "api": "https://api.sb/patentpad.com", "task": { "$id": "https://api.sb/patentpad.com/tasks/task_1", "$type": "Task", "status": "pending", "mode": "try" }, "action": { "$id": "https://api.sb/patentpad.com/actions/action_1", "operation": "Task.return", "status": "done" }, "links": { "self": "https://api.sb/patentpad.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const task = await $.Task.return({ task: 'task_1', reason: 'Example reason' }) ``` **CLI** ```bash npx startup-builder do Task.return --json '{"task":"task_1","reason":"Example reason"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Task.return({ task: 'task_1', reason: 'Example reason' })" } } ``` # Team URL: /business/nouns/team · Id: `noun:team` > A Team is a named group of Roles under one owner; every Startup starts with eleven default Teams. A Team is a named group of [Roles](/business/nouns/role) under one owner; every [Startup](/business/nouns/startup) starts with eleven default Teams. Most stay asleep until their [Trigger](/business/nouns/trigger) wakes them. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `mission` | `text` | Yes | What the Team is for, in one sentence. | | `status` | `string` | Yes | One of `asleep` or `awake`: whether any of its Processes is on. | ## Object ```json { "$id": "https://api.sb/routewise.dev/teams/team_1", "$type": "Team", "mission": "Example mission", "status": "asleep" } ``` ## Relationships - A Team **groups** many [Roles](/business/nouns/role): a Team groups the [Roles](/business/nouns/role) that do one kind of work under one owner. `groups`, inverse [`team`](/business/nouns/role#rel-team). - A Team **serves** many [Startups](/business/nouns/startup): a Team does its one kind of work for every [Startup](/business/nouns/startup) it serves; a Startup wakes a Team when its trigger [Event](/business/nouns/event) happens. `serves`, inverse [`teams`](/business/nouns/startup#rel-teams). ## Lifecycle | State | Meaning | Moves to | | --- | --- | --- | | `asleep` (first) | None of its Processes is on, so its Roles hold no work. | `awake` on [`Process.enabled`](/business/events/Process.enabled) when the Process belongs to this Team; `awake` on [`Startup.built`](/business/events/Startup.built) when the Startup’s Templates turn on one of this Team’s Processes | | `awake` | At least one of its Processes is on, and its Roles do that work. | `asleep` on [`Process.paused`](/business/events/Process.paused) when no other Process of this Team is on | ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Team.create](/business/nouns/team/create) | Creates a Team. Inherited from [Noun](/business/nouns/noun). | None. | `Team.created` | Two-way: `try`, `send`, `do` | | [Team.get](/business/nouns/team/get) | Returns one Team by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Team.list](/business/nouns/team/list) | Returns Teams, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Team.update](/business/nouns/team/update) | Changes the given properties of a Team. Inherited from [Noun](/business/nouns/noun). | None. | `Team.updated` | Two-way: `try`, `send`, `do` | | [Team.delete](/business/nouns/team/delete) | Deletes a Team; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Team.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Team.create` | Yes | Yes | Yes | No | | `Team.get` | Yes | Yes | Yes | Yes | | `Team.list` | Yes | Yes | Yes | Yes | | `Team.update` | Yes | Yes | Yes | No | | `Team.delete` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Add a team to LedgerLark. ``` **API** ```bash curl -X POST https://api.sb/ledgerlark.com/teams \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"mission":"Example mission"}' ``` ```json { "api": "https://api.sb/ledgerlark.com", "team": { "$id": "https://api.sb/ledgerlark.com/teams/team_1", "$type": "Team", "mission": "Example mission", "status": "asleep" }, "action": { "$id": "https://api.sb/ledgerlark.com/actions/action_1", "operation": "Team.create", "status": "done" }, "links": { "self": "https://api.sb/ledgerlark.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const team = await $.Team.create({ mission: 'Example mission' }) ``` **CLI** ```bash npx startup-builder do Team.create --json '{"mission":"Example mission"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Team.create({ mission: 'Example mission' })" } } ``` ## Example The [Customer Team](/agents/customer) of a tutoring marketplace wakes when the first parent accepts an [Offer](/business/nouns/offer). It groups the [Customer Lead](/agents/customer/customer-lead), [Onboarding Specialist](/agents/customer/onboarding-specialist) and [Success Manager](/agents/customer/success-manager) Roles under one owner. # extend URL: /business/nouns/template/extend · Id: `verb:Template.extend` · Call: `await $.Template.extend({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Extend adds a Template to a Startup’s bases, pinned to a Version, so the Startup inherits its definition. Extend adds a [Template](/business/nouns/template) to a [Startup](/business/nouns/startup)’s bases, pinned to a [Version](/business/nouns/version), so the Startup inherits its definition. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `template` | [Template](/business/nouns/template) | Yes | The Template to inherit. | | `startup` | [Startup](/business/nouns/startup) | Yes | The Startup that extends it. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `startup` | [Startup](/business/nouns/startup) | Yes | The Startup with the Template among its bases. | | `template` | [Template](/business/nouns/template) | Yes | The Template extended. | ## Effects - Emits [`Template.extended`](/business/events/Template.extended). - Pins the Template’s current Version in the Startup’s lockfile. - Refuses a clash between two bases until the Startup settles it. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Template.extend](/business/nouns/template/extend) | | The record is not in a state that allows this Verb, so the call is refused. | [`refused`](/code/api/errors/refused) | Read the record, run the Verb that moves it to an allowed state, then retry. | [Template.extend](/business/nouns/template/extend) | | A clash between two bases until the Startup settles it | [`refused`](/code/api/errors/refused) | Clear what the check names, then call it again. | [Template.extend](/business/nouns/template/extend) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Extend the latest template with a startup. ``` **API** ```bash curl -X POST https://api.sb/quietcopy.com/templates/template_1/extend \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"startup":"startup_1"}' ``` ```json { "api": "https://api.sb/quietcopy.com", "startup": { "$id": "https://api.sb/quietcopy.com/startups/startup_1", "$type": "Startup", "name": "QuietCopy" }, "template": { "$id": "https://api.sb/quietcopy.com/templates/template_1", "$type": "Template", "body": "Example body" }, "action": { "$id": "https://api.sb/quietcopy.com/actions/action_1", "operation": "Template.extend", "status": "done" }, "links": { "self": "https://api.sb/quietcopy.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { startup, template } = await $.Template.extend({ template: 'template_1', startup: 'startup_1' }) ``` **CLI** ```bash npx startup-builder do Template.extend --json '{"template":"template_1","startup":"startup_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Template.extend({ template: 'template_1', startup: 'startup_1' })" } } ``` # Template URL: /business/nouns/template · Id: `noun:template` > A Template is reusable Content with variables, filled from Things in the graph and authored as MDX, rendering a Message, Document, or Page. A Template is an inheritable [Startup](/business/nouns/startup) definition that a new Startup extends, overriding anything it inherits. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `body` | `text` | Yes | The MDX source with its variables. | ## Object ```json { "$id": "https://api.sb/tutorloop.com/templates/template_1", "$type": "Template", "body": "Example body" } ``` ## Relationships - A Template **generates** many [Documents](/business/nouns/document): a Template fills its variables from the graph to generate a [Document](/business/nouns/document), such as a proposal or an invoice. `generates`, inverse [`generatedFrom`](/business/nouns/document#rel-generated-from). - A Template **places** many [Components](/business/nouns/component): a Template places named [Components](/business/nouns/component), such as `Pricing`, and fills their props from records. `places`, inverse [`placedBy`](/business/nouns/component#rel-placed-by). - A Template **renders** many [Pages](/business/nouns/page): a Template fills one [Page](/business/nouns/page) per [Thing](/business/nouns/thing) or per member of a [Collection](/business/nouns/collection). `renders`, inverse [`renderedWith`](/business/nouns/page#rel-rendered-with). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Template.extend](/business/nouns/template/extend) | Extend adds a Template to a Startup’s bases, pinned to a Version, so the Startup inherits its definition. | [Agent](/business/nouns/agent) | [`Template.extended`](/business/events/Template.extended) | None. | | [Template.promote](/business/nouns/template/promote) | Promote moves one Startup’s refinement into a Template, so every Startup that extends the Template inherits it. | [Agent](/business/nouns/agent) | [`Template.promoted`](/business/events/Template.promoted) | None. | | [Template.upgrade](/business/nouns/template/upgrade) | Upgrade moves a Startup to a newer Version of a Template it extends, through a Change it can review. | [Agent](/business/nouns/agent) | [`Template.upgraded`](/business/events/Template.upgraded) | None. | | [Template.create](/business/nouns/template/create) | Creates a Template. Inherited from [Noun](/business/nouns/noun). | None. | `Template.created` | Two-way: `try`, `send`, `do` | | [Template.get](/business/nouns/template/get) | Returns one Template by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Template.list](/business/nouns/template/list) | Returns Templates, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Template.update](/business/nouns/template/update) | Changes the given properties of a Template. Inherited from [Noun](/business/nouns/noun). | None. | `Template.updated` | Two-way: `try`, `send`, `do` | | [Template.delete](/business/nouns/template/delete) | Deletes a Template; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Template.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Template.create` | Yes | Yes | Yes | No | | `Template.get` | Yes | Yes | Yes | Yes | | `Template.list` | Yes | Yes | Yes | Yes | | `Template.update` | Yes | Yes | Yes | No | | `Template.delete` | Yes | Yes | Yes | No | | `Template.extend` | Yes | Yes | Yes | No | | `Template.promote` | Yes | Yes | Yes | No | | `Template.upgrade` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Extend the latest template with a startup. ``` **API** ```bash curl -X POST https://api.sb/quietcopy.com/templates/template_1/extend \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"startup":"startup_1"}' ``` ```json { "api": "https://api.sb/quietcopy.com", "startup": { "$id": "https://api.sb/quietcopy.com/startups/startup_1", "$type": "Startup", "name": "QuietCopy" }, "template": { "$id": "https://api.sb/quietcopy.com/templates/template_1", "$type": "Template", "body": "Example body" }, "action": { "$id": "https://api.sb/quietcopy.com/actions/action_1", "operation": "Template.extend", "status": "done" }, "links": { "self": "https://api.sb/quietcopy.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { startup, template } = await $.Template.extend({ template: 'template_1', startup: 'startup_1' }) ``` **CLI** ```bash npx startup-builder do Template.extend --json '{"template":"template_1","startup":"startup_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Template.extend({ template: 'template_1', startup: 'startup_1' })" } } ``` ## Example A Startup that sells a collections [Agent](/business/nouns/agent) extends the [Agent as a Service](/products/templates/agent-as-a-service) Template, then overrides the default [Price](/business/nouns/price) to $150 a month. # promote URL: /business/nouns/template/promote · Id: `verb:Template.promote` · Call: `await $.Template.promote({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Promote moves one Startup’s refinement into a Template, so every Startup that extends the Template inherits it. Promote moves one [Startup](/business/nouns/startup)’s refinement into a [Template](/business/nouns/template), so every Startup that extends the Template inherits it. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `template` | [Template](/business/nouns/template) | Yes | The Template that receives the refinement. | | `startup` | [Startup](/business/nouns/startup) | Yes | The Startup that holds the refinement. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `change` | [Change](/business/nouns/change) | Yes | The Change against the Template. | | `template` | [Template](/business/nouns/template) | Yes | The Template that received the refinement. | ## Effects - Emits [`Template.promoted`](/business/events/Template.promoted). - Opens a Change against the Template. - Reaches each extending Startup as an `upgrade`. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Template.promote](/business/nouns/template/promote) | | The record is not in a state that allows this Verb, so the call is refused. | [`refused`](/code/api/errors/refused) | Read the record, run the Verb that moves it to an allowed state, then retry. | [Template.promote](/business/nouns/template/promote) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Promote the latest template with a startup. ``` **API** ```bash curl -X POST https://api.sb/petpantry.shop/templates/template_1/promote \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"startup":"startup_1"}' ``` ```json { "api": "https://api.sb/petpantry.shop", "change": { "$id": "https://api.sb/petpantry.shop/changes/change_1", "$type": "Change", "status": "Open", "base": "version_1" }, "template": { "$id": "https://api.sb/petpantry.shop/templates/template_1", "$type": "Template", "body": "Example body" }, "action": { "$id": "https://api.sb/petpantry.shop/actions/action_1", "operation": "Template.promote", "status": "done" }, "links": { "self": "https://api.sb/petpantry.shop/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { change, template } = await $.Template.promote({ template: 'template_1', startup: 'startup_1' }) ``` **CLI** ```bash npx startup-builder do Template.promote --json '{"template":"template_1","startup":"startup_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Template.promote({ template: 'template_1', startup: 'startup_1' })" } } ``` # upgrade URL: /business/nouns/template/upgrade · Id: `verb:Template.upgrade` · Call: `await $.Template.upgrade({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Upgrade moves a Startup to a newer Version of a Template it extends, through a Change it can review. Upgrade moves a [Startup](/business/nouns/startup) to a newer [Version](/business/nouns/version) of a [Template](/business/nouns/template) it extends, through a [Change](/business/nouns/change) it can review. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `template` | [Template](/business/nouns/template) | Yes | The Template to upgrade. | | `startup` | [Startup](/business/nouns/startup) | Yes | The Startup that extends it. | | `version` | [Version](/business/nouns/version) | No | The target Version. Defaults to the latest. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `change` | [Change](/business/nouns/change) | Yes | The Change that moves the pin. | | `template` | [Template](/business/nouns/template) | Yes | The Template upgraded to. | ## Effects - Emits [`Template.upgraded`](/business/events/Template.upgraded). - Opens a Change; nothing moves until it merges. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Template.upgrade](/business/nouns/template/upgrade) | | The record is not in a state that allows this Verb, so the call is refused. | [`refused`](/code/api/errors/refused) | Read the record, run the Verb that moves it to an allowed state, then retry. | [Template.upgrade](/business/nouns/template/upgrade) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Upgrade the latest template with a startup. ``` **API** ```bash curl -X POST https://api.sb/petpantry.shop/templates/template_1/upgrade \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"startup":"startup_1"}' ``` ```json { "api": "https://api.sb/petpantry.shop", "change": { "$id": "https://api.sb/petpantry.shop/changes/change_1", "$type": "Change", "status": "Open", "base": "version_1" }, "template": { "$id": "https://api.sb/petpantry.shop/templates/template_1", "$type": "Template", "body": "Example body" }, "action": { "$id": "https://api.sb/petpantry.shop/actions/action_1", "operation": "Template.upgrade", "status": "done" }, "links": { "self": "https://api.sb/petpantry.shop/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { change, template } = await $.Template.upgrade({ template: 'template_1', startup: 'startup_1' }) ``` **CLI** ```bash npx startup-builder do Template.upgrade --json '{"template":"template_1","startup":"startup_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Template.upgrade({ template: 'template_1', startup: 'startup_1' })" } } ``` # Tenant URL: /business/nouns/tenant · Id: `noun:tenant` > A Tenant is the partition of a Startup’s data that belongs to one Customer. A Tenant is the partition of a [Startup](/business/nouns/startup)’s data that belongs to one [Customer](/business/nouns/customer). ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `placement` | `string` | No | Where the Tenant sits in an address: `path` or `host`. | | `apiVersion` | `string` | No | The API version an unversioned call with this Tenant’s keys answers at; set at creation, moved only by `pin`. | ## Object ```json { "$id": "https://api.sb/petpantry.shop/tenants/tenant_1", "$type": "Tenant", "placement": "path", "apiVersion": "v2" } ``` ## Relationships - A Tenant **admits** many [People](/business/nouns/person): a [Person](/business/nouns/person) joins a [Customer](/business/nouns/customer)’s Tenant as a member, and one Person can join many Tenants. `admits`, inverse [`joins`](/business/nouns/person#rel-joins). - A Tenant **has** many [API Keys](/business/nouns/api-key): every call it signs reads and writes only that [Customer](/business/nouns/customer)’s records. `apiKeys`, inverse [`reaches`](/business/nouns/api-key#rel-reaches). - A Tenant’s **hostnames** are many [Domains](/business/nouns/domain): a Tenant answers on the names its [Customer](/business/nouns/customer) connects; each such [Domain](/business/nouns/domain) serves one Tenant. `hostnames`, inverse [`serves`](/business/nouns/domain#rel-serves). - A Tenant **is owned by** one [Customer](/business/nouns/customer): each [Customer](/business/nouns/customer) has one Tenant: the partition of the [Startup](/business/nouns/startup)’s data that no other Customer reads. `ownedBy`, inverse [`owns`](/business/nouns/customer#rel-owns). - A Tenant **is provisioned by** many [Member Directories](/business/nouns/member-directory): a [Member Directory](/business/nouns/member-directory) fills and empties [Roles](/business/nouns/role) in one Tenant as people join and leave the [Customer](/business/nouns/customer). `provisionedBy`, inverse [`provisions`](/business/nouns/member-directory#rel-provisions). - A Tenant **signs in via** many [SSO Connections](/business/nouns/sso-connection): a Tenant’s people sign in through its [SSO Connections](/business/nouns/sso-connection); the [Customer](/business/nouns/customer)’s admin owns each one. `signsInVia`, inverse [`serves`](/business/nouns/sso-connection#rel-serves). - A Tenant **verifies** many [Domains](/business/nouns/domain): a Tenant proves control of its [Customer](/business/nouns/customer)’s email domain, so sign-ins on that domain follow the Tenant’s policy. `verifies`, inverse [`verifiedBy`](/business/nouns/domain#rel-verified-by). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Tenant.invite](/business/nouns/tenant/invite) | Invite asks a Person to join a Customer’s Tenant, and resizes the Subscription when the Offer prices per member. | [Security Engineer](/agents/engineering/security-engineer) | [`Tenant.invited`](/business/events/Tenant.invited) | Two-way: `try`, `send`, `do` | | [Tenant.pin](/business/nouns/tenant/pin) | Pin moves a Tenant’s keys to another API version, or to `latest`, once a call with its test key passes there. | [Customer](/business/nouns/customer) | [`Tenant.pinned`](/business/events/Tenant.pinned) | Two-way: `try`, `send`, `do` | | [Tenant.provision](/business/nouns/tenant/provision) | Provision creates a Customer’s Tenant in a Startup’s App, holding that Customer’s records apart from every other. | [Integration Engineer](/agents/engineering/integration-engineer) | [`Tenant.provisioned`](/business/events/Tenant.provisioned) | None. | | [Tenant.requestSetup](/business/nouns/tenant/request-setup) | RequestSetup sends a Customer’s admin a link to connect their own sign-in, directory or verified domain to the Tenant. | [Security Engineer](/agents/engineering/security-engineer) | [`Tenant.setupRequested`](/business/events/Tenant.setupRequested) | Two-way: `try`, `send`, `do` | | [Tenant.create](/business/nouns/tenant/create) | Creates a Tenant. Inherited from [Noun](/business/nouns/noun). | None. | `Tenant.created` | Two-way: `try`, `send`, `do` | | [Tenant.get](/business/nouns/tenant/get) | Returns one Tenant by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Tenant.list](/business/nouns/tenant/list) | Returns Tenants, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Tenant.update](/business/nouns/tenant/update) | Changes the given properties of a Tenant. Inherited from [Noun](/business/nouns/noun). | None. | `Tenant.updated` | Two-way: `try`, `send`, `do` | | [Tenant.delete](/business/nouns/tenant/delete) | Deletes a Tenant; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Tenant.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Tenant.create` | Yes | Yes | Yes | No | | `Tenant.get` | Yes | Yes | Yes | Yes | | `Tenant.list` | Yes | Yes | Yes | Yes | | `Tenant.update` | Yes | Yes | Yes | No | | `Tenant.delete` | Yes | Yes | Yes | No | | `Tenant.invite` | Yes | Yes | Yes | No | | `Tenant.pin` | Yes | Yes | Yes | No | | `Tenant.provision` | Yes | Yes | Yes | No | | `Tenant.requestSetup` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Provision the latest tenant with a customer. ``` **API** ```bash curl -X POST https://api.sb/routewise.dev/tenants/provision \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"customer":"customer_1"}' ``` ```json { "api": "https://api.sb/routewise.dev", "tenant": { "$id": "https://api.sb/routewise.dev/tenants/tenant_1", "$type": "Tenant", "placement": "path", "apiVersion": "v2" }, "action": { "$id": "https://api.sb/routewise.dev/actions/action_1", "operation": "Tenant.provision", "status": "done" }, "links": { "self": "https://api.sb/routewise.dev/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const tenant = await $.Tenant.provision({ customer: 'customer_1' }) ``` **CLI** ```bash npx startup-builder do Tenant.provision --json '{"customer":"customer_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Tenant.provision({ customer: 'customer_1' })" } } ``` ## Example A recruiting agency's Tenant in a candidate-tracking [SaaS](/products/templates/saas) holds its 40,000 candidates, its API keys, and its usage. No other [Customer](/business/nouns/customer) reads it. # invite URL: /business/nouns/tenant/invite · Id: `verb:Tenant.invite` · Call: `await $.Tenant.invite({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Invite asks a Person to join a Customer’s Tenant, and resizes the Subscription when the Offer prices per member. Invite asks a [Person](/business/nouns/person) to join a [Customer](/business/nouns/customer)’s [Tenant](/business/nouns/tenant), and resizes the [Subscription](/business/nouns/subscription) when the [Offer](/business/nouns/offer) prices per member. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `tenant` | [Tenant](/business/nouns/tenant) | Yes | The Customer’s Tenant. | | `email` | `email` | Yes | Where the invitation goes. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `person` | [Person](/business/nouns/person) | Yes | The invited Person. | | `tenant` | [Tenant](/business/nouns/tenant) | Yes | The Tenant the Person was invited to. | ## Effects - Emits [`Tenant.invited`](/business/events/Tenant.invited). - Performed by the [Security Engineer](/agents/engineering/security-engineer). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Adds one unit through `Subscription.resize` when no unit is free. - Grants the Tenant’s Entitlements to the Person once they accept. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Tenant.invite](/business/nouns/tenant/invite) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Invite the latest tenant. ``` **API** ```bash curl -X POST https://api.sb/routewise.dev/tenants/tenant_1/invite \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"email":"hana@routewise.dev"}' ``` ```json { "api": "https://api.sb/routewise.dev", "person": { "$id": "https://api.sb/routewise.dev/people/person_1", "$type": "Person", "name": "Hana Sato" }, "tenant": { "$id": "https://api.sb/routewise.dev/tenants/tenant_1", "$type": "Tenant", "placement": "path", "apiVersion": "v2" }, "action": { "$id": "https://api.sb/routewise.dev/actions/action_1", "operation": "Tenant.invite", "status": "done" }, "links": { "self": "https://api.sb/routewise.dev/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { person, tenant } = await $.Tenant.invite({ tenant: 'tenant_1', email: 'hana@routewise.dev' }) ``` **CLI** ```bash npx startup-builder do Tenant.invite --json '{"tenant":"tenant_1","email":"hana@routewise.dev"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Tenant.invite({ tenant: 'tenant_1', email: 'hana@routewise.dev' })" } } ``` Guides that call it: [Let customers sign in](/products/app/let-customers-sign-in). # pin URL: /business/nouns/tenant/pin · Id: `verb:Tenant.pin` · Call: `await $.Tenant.pin({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Pin moves a Tenant’s keys to another API version, or to `latest`, once a call with its test key passes there. Pin moves a [Tenant](/business/nouns/tenant)’s keys to another API version, or to `latest`, once a call with its test key passes there. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `tenant` | [Tenant](/business/nouns/tenant) | Yes | The Tenant whose keys move. | | `apiVersion` | `string` | Yes | The version to answer at, such as `v2`, or `latest` to track the newest. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `tenant` | [Tenant](/business/nouns/tenant) | Yes | The Tenant, answering at its new version. | ## Effects - Emits [`Tenant.pinned`](/business/events/Tenant.pinned). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Refuses until a call with the Tenant’s test key succeeds at the target version. - Leaves each Watch at the version current when it was created. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Tenant.pin](/business/nouns/tenant/pin) | | Until a call with the Tenant’s test key succeeds at the target version | [`refused`](/code/api/errors/refused) | Clear what the check names, then call it again. | [Tenant.pin](/business/nouns/tenant/pin) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Pin the latest tenant. ``` **API** ```bash curl -X POST https://api.sb/patentpad.com/tenants/tenant_1/pin \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"apiVersion":"v2"}' ``` ```json { "api": "https://api.sb/patentpad.com", "tenant": { "$id": "https://api.sb/patentpad.com/tenants/tenant_1", "$type": "Tenant", "placement": "path", "apiVersion": "v2" }, "action": { "$id": "https://api.sb/patentpad.com/actions/action_1", "operation": "Tenant.pin", "status": "done" }, "links": { "self": "https://api.sb/patentpad.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const tenant = await $.Tenant.pin({ tenant: 'tenant_1', apiVersion: 'v2' }) ``` **CLI** ```bash npx startup-builder do Tenant.pin --json '{"tenant":"tenant_1","apiVersion":"v2"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Tenant.pin({ tenant: 'tenant_1', apiVersion: 'v2' })" } } ``` # provision URL: /business/nouns/tenant/provision · Id: `verb:Tenant.provision` · Call: `await $.Tenant.provision({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Provision creates a Customer’s Tenant in a Startup’s App, holding that Customer’s records apart from every other. Provision creates a [Customer](/business/nouns/customer)’s [Tenant](/business/nouns/tenant) in a [Startup](/business/nouns/startup)’s [App](/business/nouns/app), holding that Customer’s records apart from every other. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `customer` | [Customer](/business/nouns/customer) | Yes | The Customer the Tenant serves. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `tenant` | [Tenant](/business/nouns/tenant) | Yes | The new Tenant. | ## Effects - Emits [`Tenant.provisioned`](/business/events/Tenant.provisioned). - Performed by the [Integration Engineer](/agents/engineering/integration-engineer). - Grants the Entitlements of the Customer’s accepted Offers inside the Tenant. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The operation is part of an Offer the caller has not accepted or paid for. | [`payment-required`](/code/api/errors/payment-required) | Accept the Offer named in the response, then retry the call. | [Offer.accept](/business/nouns/offer/accept) | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Tenant.provision](/business/nouns/tenant/provision) | | The record is not in a state that allows this Verb, so the call is refused. | [`refused`](/code/api/errors/refused) | Read the record, run the Verb that moves it to an allowed state, then retry. | [Tenant.provision](/business/nouns/tenant/provision) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Provision the latest tenant with a customer. ``` **API** ```bash curl -X POST https://api.sb/routewise.dev/tenants/provision \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"customer":"customer_1"}' ``` ```json { "api": "https://api.sb/routewise.dev", "tenant": { "$id": "https://api.sb/routewise.dev/tenants/tenant_1", "$type": "Tenant", "placement": "path", "apiVersion": "v2" }, "action": { "$id": "https://api.sb/routewise.dev/actions/action_1", "operation": "Tenant.provision", "status": "done" }, "links": { "self": "https://api.sb/routewise.dev/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const tenant = await $.Tenant.provision({ customer: 'customer_1' }) ``` **CLI** ```bash npx startup-builder do Tenant.provision --json '{"customer":"customer_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Tenant.provision({ customer: 'customer_1' })" } } ``` Next: [`Tenant.invite`](/business/nouns/tenant/invite) (in `guide:let-customers-sign-in`). Guides that call it: [Let customers sign in](/products/app/let-customers-sign-in), [Store my customers' data](/products/app/store-my-customers-data). # requestSetup URL: /business/nouns/tenant/request-setup · Id: `verb:Tenant.requestSetup` · Call: `await $.Tenant.requestSetup({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > RequestSetup sends a Customer’s admin a link to connect their own sign-in, directory or verified domain to the Tenant. RequestSetup sends a [Customer](/business/nouns/customer)’s admin a link to connect their own sign-in, directory or verified domain to the [Tenant](/business/nouns/tenant). ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `tenant` | [Tenant](/business/nouns/tenant) | Yes | The Tenant to set up. | | `admin` | [Person](/business/nouns/person) | Yes | The Customer’s admin who receives the link. | | `intent` | `string` | Yes | What the link sets up. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `link` | `url` | Yes | The single-use setup link, valid for 7 days. | | `tenant` | [Tenant](/business/nouns/tenant) | Yes | The Tenant being set up. | ## Effects - Emits [`Tenant.setupRequested`](/business/events/Tenant.setupRequested). - Performed by the [Security Engineer](/agents/engineering/security-engineer). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Sends the link to the admin; it sets up only what it names. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Tenant.requestSetup](/business/nouns/tenant/request-setup) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Request setup the latest tenant with a person. ``` **API** ```bash curl -X POST https://api.sb/tutorloop.com/tenants/tenant_1/requestSetup \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"admin":"person_1","intent":"sso"}' ``` ```json { "api": "https://api.sb/tutorloop.com", "link": "https://tutorloop.com", "tenant": { "$id": "https://api.sb/tutorloop.com/tenants/tenant_1", "$type": "Tenant", "placement": "path", "apiVersion": "v2" }, "action": { "$id": "https://api.sb/tutorloop.com/actions/action_1", "operation": "Tenant.requestSetup", "status": "done" }, "links": { "self": "https://api.sb/tutorloop.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { link, tenant } = await $.Tenant.requestSetup({ tenant: 'tenant_1', admin: 'person_1', intent: 'sso' }) ``` **CLI** ```bash npx startup-builder do Tenant.requestSetup --json '{"tenant":"tenant_1","admin":"person_1","intent":"sso"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Tenant.requestSetup({ tenant: 'tenant_1', admin: 'person_1', intent: 'sso' })" } } ``` Next: [`SSOConnection.activate`](/business/nouns/sso-connection/activate) (in `guide:set-up-sso-for-a-customer`). Guides that call it: [Set up SSO for a customer](/products/app/set-up-sso-for-a-customer). # Theme URL: /business/nouns/theme · Id: `noun:theme` > A Theme is the design tokens of a Brand, its color, type, spacing, radius, and motion, that every Component reads when it renders. A Theme is the design tokens of a [Brand](/business/nouns/brand), its color, type, spacing, radius, and motion, that every [Component](/business/nouns/component) reads when it renders. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `tokens` | `json` | Yes | The token values, in light and dark modes. | | `css` | `text` | No | Extra CSS, applied after the tokens. | ## Object ```json { "$id": "https://api.sb/ledgerlark.com/themes/theme_1", "$type": "Theme", "tokens": {}, "css": ":root { --radius: 6px; }" } ``` ## Relationships - A Theme **themes** many [Brands](/business/nouns/brand): a Theme sets a [Brand](/business/nouns/brand)’s color, type, spacing and motion. `themes`, inverse [`themedBy`](/business/nouns/brand#rel-themed-by). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Theme.create](/business/nouns/theme/create) | Creates a Theme. Inherited from [Noun](/business/nouns/noun). | None. | `Theme.created` | Two-way: `try`, `send`, `do` | | [Theme.get](/business/nouns/theme/get) | Returns one Theme by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Theme.list](/business/nouns/theme/list) | Returns Themes, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Theme.update](/business/nouns/theme/update) | Changes the given properties of a Theme. Inherited from [Noun](/business/nouns/noun). | None. | `Theme.updated` | Two-way: `try`, `send`, `do` | | [Theme.delete](/business/nouns/theme/delete) | Deletes a Theme; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Theme.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Theme.create` | Yes | Yes | Yes | No | | `Theme.get` | Yes | Yes | Yes | Yes | | `Theme.list` | Yes | Yes | Yes | Yes | | `Theme.update` | Yes | Yes | Yes | No | | `Theme.delete` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Add a theme to PatentPad. ``` **API** ```bash curl -X POST https://api.sb/patentpad.com/themes \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"tokens":{}}' ``` ```json { "api": "https://api.sb/patentpad.com", "theme": { "$id": "https://api.sb/patentpad.com/themes/theme_1", "$type": "Theme", "tokens": {} }, "action": { "$id": "https://api.sb/patentpad.com/actions/action_1", "operation": "Theme.create", "status": "done" }, "links": { "self": "https://api.sb/patentpad.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const theme = await $.Theme.create({ tokens: {} }) ``` **CLI** ```bash npx startup-builder do Theme.create --json '{"tokens":{}}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Theme.create({ tokens: {} })" } } ``` ## Example ```json { "color": { "light": { "accent": "oklch(52% 0.08 200)", "ink": "oklch(24% 0.02 220)", "paper": "oklch(98% 0.004 200)" }, "dark": { "accent": "oklch(70% 0.08 200)", "ink": "oklch(93% 0.01 200)", "paper": "oklch(19% 0.02 220)" } }, "font": { "display": "Newsreader", "body": "Public Sans" }, "radius": { "card": "6px" }, "motion": { "duration": "200ms", "easing": "ease-out", "reduce": "0ms" } } ``` # Thing URL: /business/nouns/thing · Id: `noun:thing` > A Thing is an instance of one or more Nouns, with an identity, a current state, and the union of their properties. A Thing is an instance of one or more [Nouns](/business/nouns/noun), with an identity, a current state, and the union of their properties. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `id` | `string` | Yes | The stable identifier, which never changes. | | `type` | list of [Noun](/business/nouns/noun) | Yes | The Nouns this Thing is an instance of. | | `state` | `string` | No | The current state in its lifecycle. | | `outside` | `json` | No | The ids this Thing has in outside tools, one per Integration, so a re-run matches instead of duplicating. | ## Object ```json { "$id": "https://api.sb/quietcopy.com/things/thing_1", "$type": "Thing", "id": "Example id", "type": [ "noun_1" ], "state": "Example state", "outside": {} } ``` ## Relationships - A Thing **is acted on by** many [Actions](/business/nouns/action): the Thing an [Action](/business/nouns/action) changes; a Thing’s history is the Actions that acted on it. `actedOnBy`, inverse [`actsOn`](/business/nouns/action#rel-acts-on). - A Thing **aims for** many [Goals](/business/nouns/goal): every Thing pursues [Goals](/business/nouns/goal), such as a [Startup](/business/nouns/startup)’s quarterly objective or a [Team](/business/nouns/team)’s weekly target. `aimsFor`, inverse [`heldBy`](/business/nouns/goal#rel-held-by). - A Thing **has** many [Comments](/business/nouns/comment): a [Comment](/business/nouns/comment) is an internal note on one Thing, never sent to a [Contact](/business/nouns/contact). `comments`, inverse [`annotates`](/business/nouns/comment#rel-annotates). - A Thing **is configured by** many [Settings](/business/nouns/setting): the Thing whose choice a [Setting](/business/nouns/setting) holds; everything below it inherits the value unless it sets its own. `configuredBy`, inverse [`configures`](/business/nouns/setting#rel-configures). - A Thing **has** many [Dashboards](/business/nouns/dashboard): a [Dashboard](/business/nouns/dashboard) summarizes one scope, such as a [Studio](/business/nouns/studio), a [Startup](/business/nouns/startup), a [Team](/business/nouns/team), or a [Role](/business/nouns/role). `dashboards`, inverse [`views`](/business/nouns/dashboard#rel-views). - A Thing **is decided by** many [Decisions](/business/nouns/decision): a [Decision](/business/nouns/decision) records one choice about a Thing and stays on that Thing’s record forever. `decidedBy`, inverse [`decides`](/business/nouns/decision#rel-decides). - A Thing **is an instance of** many [Nouns](/business/nouns/noun): a Thing takes the properties, relationships and [Verbs](/business/nouns/verb) of every [Noun](/business/nouns/noun) it is an instance of. `instanceOf`, inverse [`instances`](/business/nouns/noun#rel-instances). - A Thing **has** many [Issues](/business/nouns/issue): an [Issue](/business/nouns/issue) is about one Thing, such as a [Product](/business/nouns/product), a [Page](/business/nouns/page), or an [Order](/business/nouns/order). `issues`, inverse [`reports`](/business/nouns/issue#rel-reports). - A Thing **is a member of** many [Collections](/business/nouns/collection): Members are listed one by one or matched by the [Collection](/business/nouns/collection)’s saved query; a Thing can belong to many Collections. `memberOf`, inverse [`contains`](/business/nouns/collection#rel-contains). - A Thing **is versioned as** many [Versions](/business/nouns/version): every published change to a Thing’s definition is an immutable [Version](/business/nouns/version), kept forever. `versionedAs`, inverse [`versionOf`](/business/nouns/version#rel-version-of). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Thing.relate](/business/nouns/thing/relate) | Relate links two Things by a Relationship their Nouns declare, readable from both ends at once. | [Data Engineer](/agents/engineering/data-engineer) | [`Thing.related`](/business/events/Thing.related) | Two-way: `try`, `send`, `do` | | [Thing.resolve](/business/nouns/thing/resolve) | Resolve finds the one Thing of a Noun that matches given properties, or creates it, and says which it did. | [Data Engineer](/agents/engineering/data-engineer) | [`Thing.resolved`](/business/events/Thing.resolved) | Two-way: `try`, `send`, `do` | | [Thing.share](/business/nouns/thing/share) | Share grants a person, a Role or a guest Verbs on one record and everything it contains. | [Security Engineer](/agents/engineering/security-engineer) | [`Thing.shared`](/business/events/Thing.shared) | Two-way: `try`, `send`, `do` | | [Thing.unrelate](/business/nouns/thing/unrelate) | Unrelate ends a Relationship between two Things; the link stays in history and reads back at any earlier moment. | [Data Engineer](/agents/engineering/data-engineer) | [`Thing.unrelated`](/business/events/Thing.unrelated) | Two-way: `try`, `send`, `do` | | [Thing.create](/business/nouns/thing/create) | Creates a Thing. Inherited from [Noun](/business/nouns/noun). | None. | `Thing.created` | Two-way: `try`, `send`, `do` | | [Thing.get](/business/nouns/thing/get) | Returns one Thing by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Thing.list](/business/nouns/thing/list) | Returns Things, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Thing.update](/business/nouns/thing/update) | Changes the given properties of a Thing. Inherited from [Noun](/business/nouns/noun). | None. | `Thing.updated` | Two-way: `try`, `send`, `do` | | [Thing.delete](/business/nouns/thing/delete) | Deletes a Thing; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Thing.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Thing.create` | Yes | Yes | Yes | No | | `Thing.get` | Yes | Yes | Yes | Yes | | `Thing.list` | Yes | Yes | Yes | Yes | | `Thing.update` | Yes | Yes | Yes | No | | `Thing.delete` | Yes | Yes | Yes | No | | `Thing.relate` | Yes | Yes | Yes | No | | `Thing.resolve` | Yes | Yes | Yes | No | | `Thing.share` | Yes | Yes | Yes | No | | `Thing.unrelate` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Share the latest thing with a party. ``` **API** ```bash curl -X POST https://api.sb/ledgerlark.com/things/thing_1/share \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"to":"party_1","verbs":["Example verbs"]}' ``` ```json { "api": "https://api.sb/ledgerlark.com", "permission": { "$id": "https://api.sb/ledgerlark.com/permissions/permission_1", "$type": "Permission", "scope": "Example scope" }, "thing": { "$id": "https://api.sb/ledgerlark.com/things/thing_1", "$type": "Thing", "id": "Example id", "type": [ "noun_1" ] }, "action": { "$id": "https://api.sb/ledgerlark.com/actions/action_1", "operation": "Thing.share", "status": "done" }, "links": { "self": "https://api.sb/ledgerlark.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { permission, thing } = await $.Thing.share({ thing: 'thing_1', to: 'party_1', verbs: ['Example verbs'] }) ``` **CLI** ```bash npx startup-builder do Thing.share --json '{"thing":"thing_1","to":"party_1","verbs":["Example verbs"]}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Thing.share({ thing: 'thing_1', to: 'party_1', verbs: ['Example verbs'] })" } } ``` ## Example One recruiting agency is a single Thing that is both an [Organization](/business/nouns/organization) and a [Customer](/business/nouns/customer), with one `id` and the properties of both Nouns. # relate URL: /business/nouns/thing/relate · Id: `verb:Thing.relate` · Call: `await $.Thing.relate({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Relate links two Things by a Relationship their Nouns declare, readable from both ends at once. Relate links two [Things](/business/nouns/thing) by a [Relationship](/business/nouns/relationship) their [Nouns](/business/nouns/noun) declare, readable from both ends at once. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `thing` | [Thing](/business/nouns/thing) | Yes | The source Thing. | | `predicate` | `string` | Yes | The Relationship as read from the source, such as `places`. | | `to` | [Thing](/business/nouns/thing) | Yes | The target Thing. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `relationship` | [Relationship](/business/nouns/relationship) | Yes | The Relationship, with its provenance. | | `thing` | [Thing](/business/nouns/thing) | Yes | The Thing the Relationship starts from. | ## Effects - Emits [`Thing.related`](/business/events/Thing.related). - Performed by the [Data Engineer](/agents/engineering/data-engineer). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Refuses a predicate that neither Noun declares. - On a to-one Relationship, replaces the old target; the old link stays in history. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Thing.relate](/business/nouns/thing/relate) | | A predicate that neither Noun declares | [`refused`](/code/api/errors/refused) | Clear what the check names, then call it again. | [Thing.relate](/business/nouns/thing/relate) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Relate the latest thing. ``` **API** ```bash curl -X POST https://api.sb/shiftnote.app/things/thing_1/relate \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"predicate":"Example predicate","to":"thing_1"}' ``` ```json { "api": "https://api.sb/shiftnote.app", "relationship": { "$id": "https://api.sb/shiftnote.app/relationships/relationship_1", "$type": "Relationship", "predicate": "Example predicate", "inverse": "Example inverse" }, "thing": { "$id": "https://api.sb/shiftnote.app/things/thing_1", "$type": "Thing", "id": "Example id", "type": [ "noun_1" ] }, "action": { "$id": "https://api.sb/shiftnote.app/actions/action_1", "operation": "Thing.relate", "status": "done" }, "links": { "self": "https://api.sb/shiftnote.app/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { relationship, thing } = await $.Thing.relate({ thing: 'thing_1', predicate: 'Example predicate', to: 'thing_1' }) ``` **CLI** ```bash npx startup-builder do Thing.relate --json '{"thing":"thing_1","predicate":"Example predicate","to":"thing_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Thing.relate({ thing: 'thing_1', predicate: 'Example predicate', to: 'thing_1' })" } } ``` # resolve URL: /business/nouns/thing/resolve · Id: `verb:Thing.resolve` · Call: `await $.Thing.resolve({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Resolve finds the one Thing of a Noun that matches given properties, or creates it, and says which it did. Resolve finds the one [Thing](/business/nouns/thing) of a [Noun](/business/nouns/noun) that matches given properties, or creates it, and says which it did. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `noun` | [Noun](/business/nouns/noun) | Yes | The Noun to resolve. | | `match` | `json` | Yes | The properties that identify the Thing, such as an email address. | | `set` | `json` | No | Properties to write on the found or created Thing. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `thing` | [Thing](/business/nouns/thing) | No | The Thing found or created; empty when held. | | `decision` | `string` | Yes | What happened: `found`, `created`, or `held` when two or more Things match. | ## Effects - Emits [`Thing.resolved`](/business/events/Thing.resolved). - Performed by the [Data Engineer](/agents/engineering/data-engineer). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - When two or more Things match, writes nothing and opens a Task to merge them. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Thing.resolve](/business/nouns/thing/resolve) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Resolve the latest thing with a noun. ``` **API** ```bash curl -X POST https://api.sb/petpantry.shop/things/resolve \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"noun":"noun_1","match":{}}' ``` ```json { "api": "https://api.sb/petpantry.shop", "thing": { "$id": "https://api.sb/petpantry.shop/things/thing_1", "$type": "Thing", "id": "Example id", "type": [ "noun_1" ] }, "decision": "found", "action": { "$id": "https://api.sb/petpantry.shop/actions/action_1", "operation": "Thing.resolve", "status": "done" }, "links": { "self": "https://api.sb/petpantry.shop/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { thing, decision } = await $.Thing.resolve({ noun: 'noun_1', match: {} }) ``` **CLI** ```bash npx startup-builder do Thing.resolve --json '{"noun":"noun_1","match":{}}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Thing.resolve({ noun: 'noun_1', match: {} })" } } ``` # share URL: /business/nouns/thing/share · Id: `verb:Thing.share` · Call: `await $.Thing.share({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Share grants a person, a Role or a guest Verbs on one record and everything it contains. Share grants a person, a [Role](/business/nouns/role) or a guest [Verbs](/business/nouns/verb) on one record and everything it contains. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `thing` | [Thing](/business/nouns/thing) | Yes | The record to share. | | `to` | [Party](/business/nouns/party) | Yes | Who receives the grant: a person, or a guest who fills only the `guest` Role. | | `verbs` | `string[]` | Yes | The Verbs granted, such as `get` and `comment`. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `permission` | [Permission](/business/nouns/permission) | Yes | The grant, scoped to the record and its contents. | | `thing` | [Thing](/business/nouns/thing) | Yes | The Thing shared. | ## Effects - Emits [`Thing.shared`](/business/events/Thing.shared). - Performed by the [Security Engineer](/agents/engineering/security-engineer). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Follows containment Relationships, so sharing a folder shares documents added later. - Widening a share follows the Approval rule for widening a Role; unsharing applies on the next call. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Thing.share](/business/nouns/thing/share) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Share the latest thing with a party. ``` **API** ```bash curl -X POST https://api.sb/ledgerlark.com/things/thing_1/share \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"to":"party_1","verbs":["Example verbs"]}' ``` ```json { "api": "https://api.sb/ledgerlark.com", "permission": { "$id": "https://api.sb/ledgerlark.com/permissions/permission_1", "$type": "Permission", "scope": "Example scope" }, "thing": { "$id": "https://api.sb/ledgerlark.com/things/thing_1", "$type": "Thing", "id": "Example id", "type": [ "noun_1" ] }, "action": { "$id": "https://api.sb/ledgerlark.com/actions/action_1", "operation": "Thing.share", "status": "done" }, "links": { "self": "https://api.sb/ledgerlark.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { permission, thing } = await $.Thing.share({ thing: 'thing_1', to: 'party_1', verbs: ['Example verbs'] }) ``` **CLI** ```bash npx startup-builder do Thing.share --json '{"thing":"thing_1","to":"party_1","verbs":["Example verbs"]}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Thing.share({ thing: 'thing_1', to: 'party_1', verbs: ['Example verbs'] })" } } ``` # unrelate URL: /business/nouns/thing/unrelate · Id: `verb:Thing.unrelate` · Call: `await $.Thing.unrelate({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Unrelate ends a Relationship between two Things; the link stays in history and reads back at any earlier moment. Unrelate ends a [Relationship](/business/nouns/relationship) between two [Things](/business/nouns/thing); the link stays in history and reads back at any earlier moment. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `thing` | [Thing](/business/nouns/thing) | Yes | The source Thing. | | `predicate` | `string` | Yes | The Relationship as read from the source. | | `to` | [Thing](/business/nouns/thing) | Yes | The target Thing. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `relationship` | [Relationship](/business/nouns/relationship) | Yes | The ended Relationship. | | `thing` | [Thing](/business/nouns/thing) | Yes | The Thing the Relationship started from. | ## Effects - Emits [`Thing.unrelated`](/business/events/Thing.unrelated). - Performed by the [Data Engineer](/agents/engineering/data-engineer). - Two-way: it runs at once, in the `try`, `send` and `do` modes. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Thing.unrelate](/business/nouns/thing/unrelate) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Unrelate the latest thing. ``` **API** ```bash curl -X POST https://api.sb/kilnbakery.com/things/thing_1/unrelate \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"predicate":"Example predicate","to":"thing_1"}' ``` ```json { "api": "https://api.sb/kilnbakery.com", "relationship": { "$id": "https://api.sb/kilnbakery.com/relationships/relationship_1", "$type": "Relationship", "predicate": "Example predicate", "inverse": "Example inverse" }, "thing": { "$id": "https://api.sb/kilnbakery.com/things/thing_1", "$type": "Thing", "id": "Example id", "type": [ "noun_1" ] }, "action": { "$id": "https://api.sb/kilnbakery.com/actions/action_1", "operation": "Thing.unrelate", "status": "done" }, "links": { "self": "https://api.sb/kilnbakery.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { relationship, thing } = await $.Thing.unrelate({ thing: 'thing_1', predicate: 'Example predicate', to: 'thing_1' }) ``` **CLI** ```bash npx startup-builder do Thing.unrelate --json '{"thing":"thing_1","predicate":"Example predicate","to":"thing_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Thing.unrelate({ thing: 'thing_1', predicate: 'Example predicate', to: 'thing_1' })" } } ``` # Thread URL: /business/nouns/thread · Id: `noun:thread` > A Thread is a set of Messages replying to one another inside a Channel. A Thread is a set of [Messages](/business/nouns/message) replying to one another inside a [Channel](/business/nouns/channel). ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `subject` | `string` | No | What the Thread is about. | ## Object ```json { "$id": "https://api.sb/kilnbakery.com/threads/thread_1", "$type": "Thread", "subject": "Example subject" } ``` ## Relationships - A Thread **groups** many [Messages](/business/nouns/message): a Thread groups [Messages](/business/nouns/message) that reply to one another. `groups`, inverse [`thread`](/business/nouns/message#rel-thread). - A Thread **is hosted in** one [Channel](/business/nouns/channel): a [Channel](/business/nouns/channel) holds Threads. `hostedIn`, inverse [`hosts`](/business/nouns/channel#rel-hosts). - A Thread **has** many [Questions](/business/nouns/question): each [Question](/business/nouns/question) posts in the Thread of the record it concerns, where free-text replies land. `questions`, inverse [`postedIn`](/business/nouns/question#rel-posted-in). - A Thread **is raised in** one [Conversation](/business/nouns/conversation): the intake Threads a support [Conversation](/business/nouns/conversation) opens, each deadline counted from the Conversation’s first [Message](/business/nouns/message). `raisedIn`, inverse [`raises`](/business/nouns/conversation#rel-raises). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Thread.create](/business/nouns/thread/create) | Creates a Thread. Inherited from [Noun](/business/nouns/noun). | None. | `Thread.created` | Two-way: `try`, `send`, `do` | | [Thread.get](/business/nouns/thread/get) | Returns one Thread by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Thread.list](/business/nouns/thread/list) | Returns Threads, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Thread.update](/business/nouns/thread/update) | Changes the given properties of a Thread. Inherited from [Noun](/business/nouns/noun). | None. | `Thread.updated` | Two-way: `try`, `send`, `do` | | [Thread.delete](/business/nouns/thread/delete) | Deletes a Thread; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Thread.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Thread.create` | Yes | Yes | Yes | No | | `Thread.get` | Yes | Yes | Yes | Yes | | `Thread.list` | Yes | Yes | Yes | Yes | | `Thread.update` | Yes | Yes | Yes | No | | `Thread.delete` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Add a thread to PetPantry. ``` **API** ```bash curl -X POST https://api.sb/petpantry.shop/threads \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"subject":"Example subject"}' ``` ```json { "api": "https://api.sb/petpantry.shop", "thread": { "$id": "https://api.sb/petpantry.shop/threads/thread_1", "$type": "Thread", "subject": "Example subject" }, "action": { "$id": "https://api.sb/petpantry.shop/actions/action_1", "operation": "Thread.create", "status": "done" }, "links": { "self": "https://api.sb/petpantry.shop/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const thread = await $.Thread.create({ subject: 'Example subject' }) ``` **CLI** ```bash npx startup-builder do Thread.create --json '{"subject":"Example subject"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Thread.create({ subject: 'Example subject' })" } } ``` ## Example A parent's question about a missed session, the tutor's reply, and the parent's follow-up form one Thread in the `help@` [Channel](/business/nouns/channel). # Tool URL: /business/nouns/tool · Id: `noun:tool` > A Tool is a Verb as a Worker reaches it through an Interface, under one name on every Interface. A Tool is a [Verb](/business/nouns/verb) as a [Worker](/business/nouns/worker) reaches it through an [Interface](/business/nouns/interface), under one name on every Interface. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `name` | `string` | Yes | The `Noun.verb` name, such as `Contact.create`. | ## Object ```json { "$id": "https://api.sb/quietcopy.com/tools/tool_1", "$type": "Tool", "name": "QuietCopy" } ``` ## Relationships - A Tool **exposes** one [Verb](/business/nouns/verb): a Tool is one [Verb](/business/nouns/verb) under one name on every [Interface](/business/nouns/interface), such as `Contact.create`. `exposes`, inverse [`exposedAs`](/business/nouns/verb#rel-exposed-as). - A Tool **is used by** many [Workers](/business/nouns/worker): the Tools a [Worker](/business/nouns/worker) may call, narrowed to its [Role](/business/nouns/role)’s [Permissions](/business/nouns/permission). `usedBy`, inverse [`uses`](/business/nouns/worker#rel-uses). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Tool.create](/business/nouns/tool/create) | Creates a Tool. Inherited from [Noun](/business/nouns/noun). | None. | `Tool.created` | Two-way: `try`, `send`, `do` | | [Tool.get](/business/nouns/tool/get) | Returns one Tool by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Tool.list](/business/nouns/tool/list) | Returns Tools, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Tool.update](/business/nouns/tool/update) | Changes the given properties of a Tool. Inherited from [Noun](/business/nouns/noun). | None. | `Tool.updated` | Two-way: `try`, `send`, `do` | | [Tool.delete](/business/nouns/tool/delete) | Deletes a Tool; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Tool.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Tool.create` | Yes | Yes | Yes | No | | `Tool.get` | Yes | Yes | Yes | Yes | | `Tool.list` | Yes | Yes | Yes | Yes | | `Tool.update` | Yes | Yes | Yes | No | | `Tool.delete` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Add a tool to TutorLoop. ``` **API** ```bash curl -X POST https://api.sb/tutorloop.com/tools \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"name":"TutorLoop"}' ``` ```json { "api": "https://api.sb/tutorloop.com", "tool": { "$id": "https://api.sb/tutorloop.com/tools/tool_1", "$type": "Tool", "name": "TutorLoop" }, "action": { "$id": "https://api.sb/tutorloop.com/actions/action_1", "operation": "Tool.create", "status": "done" }, "links": { "self": "https://api.sb/tutorloop.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const tool = await $.Tool.create({ name: 'TutorLoop' }) ``` **CLI** ```bash npx startup-builder do Tool.create --json '{"name":"TutorLoop"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Tool.create({ name: 'TutorLoop' })" } } ``` ## Example `convert_currency` is one Tool: an MCP tool for [Agents](/business/nouns/agent), a CLI command for operators, and an SDK method for developers, all exposing `Rate.convert`. # attach URL: /business/nouns/transaction/attach · Id: `verb:Transaction.attach` · Call: `await $.Transaction.attach({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Attach matches a receipt File to a card Transaction, or flags the Transaction when no receipt arrives in time. Attach matches a receipt [File](/business/nouns/file) to a card [Transaction](/business/nouns/transaction), or flags the Transaction when no receipt arrives in time. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `transaction` | [Transaction](/business/nouns/transaction) | Yes | The card Transaction. | | `file` | [File](/business/nouns/file) | No | The receipt; empty to match from the Startup’s Mailboxes. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `transaction` | [Transaction](/business/nouns/transaction) | Yes | The Transaction with its receipt. | ## Effects - Emits [`Transaction.attached`](/business/events/Transaction.attached). - Performed by the [Finance Lead](/agents/finance/finance-lead). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Reads receipts sent to the Startup’s Mailboxes and uploaded Files. - After 7 days with no receipt, opens a Task for the Role whose Mandate spent. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Transaction.attach](/business/nouns/transaction/attach) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Attach the latest transaction. ``` **API** ```bash curl -X POST https://api.sb/ledgerlark.com/transactions/transaction_1/attach \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/ledgerlark.com", "transaction": { "$id": "https://api.sb/ledgerlark.com/transactions/transaction_1", "$type": "Transaction", "kind": "charge", "amount": { "amount": 400, "currency": "USD" } }, "action": { "$id": "https://api.sb/ledgerlark.com/actions/action_1", "operation": "Transaction.attach", "status": "done" }, "links": { "self": "https://api.sb/ledgerlark.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const transaction = await $.Transaction.attach({ transaction: 'transaction_1' }) ``` **CLI** ```bash npx startup-builder do Transaction.attach --json '{"transaction":"transaction_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Transaction.attach({ transaction: 'transaction_1' })" } } ``` # categorize URL: /business/nouns/transaction/categorize · Id: `verb:Transaction.categorize` · Call: `await $.Transaction.categorize({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Categorize codes a Transaction to an account in the chart by the Startup’s Policy and flags a low-confidence code for review. Categorize codes a [Transaction](/business/nouns/transaction) to an account in the chart by the [Startup](/business/nouns/startup)’s [Policy](/business/nouns/policy) and flags a low-confidence code for review. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `transaction` | [Transaction](/business/nouns/transaction) | Yes | The Transaction to code. | | `account` | `string` | No | The account code to use in place of the Policy’s choice. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `transaction` | [Transaction](/business/nouns/transaction) | Yes | The coded Transaction. | | `account` | `string` | Yes | The account code it was coded to. | | `confidence` | `number` | Yes | How sure the code is, from 0 to 1. | ## Effects - Emits [`Transaction.categorized`](/business/events/Transaction.categorized). - Performed by the [Finance Lead](/agents/finance/finance-lead). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Below the Policy’s confidence threshold, opens a review Task for the Finance Lead. - A new code posts a reversing pair and a new pair; the first pair stays. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Transaction.categorize](/business/nouns/transaction/categorize) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Categorize the latest transaction. ``` **API** ```bash curl -X POST https://api.sb/ledgerlark.com/transactions/transaction_1/categorize \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/ledgerlark.com", "transaction": { "$id": "https://api.sb/ledgerlark.com/transactions/transaction_1", "$type": "Transaction", "kind": "charge", "amount": { "amount": 400, "currency": "USD" } }, "account": "Example account", "confidence": 1, "action": { "$id": "https://api.sb/ledgerlark.com/actions/action_1", "operation": "Transaction.categorize", "status": "done" }, "links": { "self": "https://api.sb/ledgerlark.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { transaction, account, confidence } = await $.Transaction.categorize({ transaction: 'transaction_1' }) ``` **CLI** ```bash npx startup-builder do Transaction.categorize --json '{"transaction":"transaction_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Transaction.categorize({ transaction: 'transaction_1' })" } } ``` # Transaction URL: /business/nouns/transaction · Id: `noun:transaction` > A Transaction is money moving on a payment rail, such as a charge, a payout, or a transfer, reconciled to Entries. A Transaction is money moving on a payment rail, such as a charge, a payout, or a transfer, reconciled to [Entries](/business/nouns/entry). ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `kind` | `string` | Yes | One of `charge`, `refund`, `payout`, or `transfer`. | | `amount` | `money` | Yes | The amount moved. | | `receipt` | [File](/business/nouns/file) | No | The receipt matched to a card Transaction. | | `settledAt` | `datetime` | No | When the money became available in a cash Account. | ## Object ```json { "$id": "https://api.sb/tutorloop.com/transactions/transaction_1", "$type": "Transaction", "kind": "charge", "amount": { "amount": 60, "currency": "USD" }, "receipt": "file_1", "settledAt": "2026-10-22T12:00:00Z" } ``` ## Relationships - A Transaction **reconciles** many [Entries](/business/nouns/entry): the ledger [Entries](/business/nouns/entry) the Transaction settles, matched during reconciliation. `reconciles`, inverse [`reconciledBy`](/business/nouns/entry#rel-reconciled-by). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Transaction.attach](/business/nouns/transaction/attach) | Attach matches a receipt File to a card Transaction, or flags the Transaction when no receipt arrives in time. | [Finance Lead](/agents/finance/finance-lead) | [`Transaction.attached`](/business/events/Transaction.attached) | Two-way: `try`, `send`, `do` | | [Transaction.categorize](/business/nouns/transaction/categorize) | Categorize codes a Transaction to an account in the chart by the Startup’s Policy and flags a low-confidence code for review. | [Finance Lead](/agents/finance/finance-lead) | [`Transaction.categorized`](/business/events/Transaction.categorized) | Two-way: `try`, `send`, `do` | | [Transaction.reconcile](/business/nouns/transaction/reconcile) | Reconcile matches a Transaction on a payment rail to the ledger Entries it settles. | [Finance Lead](/agents/finance/finance-lead) | [`Transaction.reconciled`](/business/events/Transaction.reconciled) | Two-way: `try`, `send`, `do` | | [Transaction.get](/business/nouns/transaction/get) | Returns one Transaction by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Transaction.list](/business/nouns/transaction/list) | Returns Transactions, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | A Transaction is kept forever and never edited: it has no `update` or `delete`. ## Events Events no Verb emits. Each Verb’s Event is in the Verbs table above; every Event is delivered in the same shape. ### Transaction.failed The rail refused a charge or payout Transaction after it was sent. Raised by the rail. | Field | Type | Required | Description | | --- | --- | --- | --- | | `name` | `string` | Yes | `Transaction.failed`. | | `at` | `datetime` | Yes | When it happened. | | `seq` | `integer` | No | Its position in the namespace, one more than the Event before; any seq is a cursor into the history. | | `data` | `json` | Yes | The Thing as the Action left it. | | `data.transaction` | [Transaction](/business/nouns/transaction) | Yes | The Transaction as the change left it. | | `data.transaction.kind` | `string` | Yes | One of `charge`, `refund`, `payout`, or `transfer`. | | `data.transaction.amount` | `money` | Yes | The amount moved. | | `data.transaction.receipt` | [File](/business/nouns/file) | No | The receipt matched to a card Transaction. | | `data.transaction.settledAt` | `datetime` | No | When the money became available in a cash Account. | | `data.reason` | `text` | Yes | Why the rail refused it, in the rail’s words. | ```json { "$id": "https://api.sb/tutorloop.com/events/event_1", "$type": "Event", "name": "Transaction.failed", "at": "2026-10-22T12:00:00Z", "data": { "transaction": { "$id": "https://api.sb/tutorloop.com/transactions/transaction_1", "$type": "Transaction", "kind": "charge", "amount": { "amount": 60, "currency": "USD" }, "receipt": "file_1", "settledAt": "2026-10-22T12:00:00Z" }, "reason": "The bank declined the transfer." }, "seq": 1 } ``` ### Transaction.settled The money in a Transaction became available in a cash Account. Raised by the rail. | Field | Type | Required | Description | | --- | --- | --- | --- | | `name` | `string` | Yes | `Transaction.settled`. | | `at` | `datetime` | Yes | When it happened. | | `seq` | `integer` | No | Its position in the namespace, one more than the Event before; any seq is a cursor into the history. | | `data` | `json` | Yes | The Thing as the Action left it. | | `data.transaction` | [Transaction](/business/nouns/transaction) | Yes | The Transaction as the change left it. | | `data.transaction.kind` | `string` | Yes | One of `charge`, `refund`, `payout`, or `transfer`. | | `data.transaction.amount` | `money` | Yes | The amount moved. | | `data.transaction.receipt` | [File](/business/nouns/file) | No | The receipt matched to a card Transaction. | | `data.transaction.settledAt` | `datetime` | No | When the money became available in a cash Account. | | `data.account` | [Account](/business/nouns/account) | Yes | The cash Account the money is in. | | `data.availableAt` | `datetime` | Yes | When the money became available. | ```json { "$id": "https://api.sb/tutorloop.com/events/event_1", "$type": "Event", "name": "Transaction.settled", "at": "2026-10-22T12:00:00Z", "data": { "transaction": { "$id": "https://api.sb/tutorloop.com/transactions/transaction_1", "$type": "Transaction", "kind": "charge", "amount": { "amount": 60, "currency": "USD" }, "receipt": "file_1", "settledAt": "2026-10-22T12:00:00Z" }, "account": { "$id": "https://api.sb/tutorloop.com/accounts/account_1", "$type": "Account", "class": "cash" }, "availableAt": "2026-10-22T12:00:00Z" }, "seq": 1 } ``` ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Transaction.get` | Yes | Yes | Yes | Yes | | `Transaction.list` | Yes | Yes | Yes | Yes | | `Transaction.attach` | Yes | Yes | Yes | No | | `Transaction.categorize` | Yes | Yes | Yes | No | | `Transaction.reconcile` | Yes | Yes | Yes | No | ## Stripe **PaymentIntent** (`payment_intent`), for a Transaction whose `kind` is `charge`. The source of truth is Stripe: db.sb mirrors it, written only from Stripe’s webhooks. | Property | Stripe field | Source of truth | | --- | --- | --- | | `amount` | `amount` | Stripe | **Payout** (`payout`), for a Transaction whose `kind` is `payout`. The source of truth is Stripe: db.sb mirrors it, written only from Stripe’s webhooks. | Property | Stripe field | Source of truth | | --- | --- | --- | | `amount` | `amount` | Stripe | **Refund** (`refund`), for a Transaction whose `kind` is `refund`. The source of truth is Stripe: db.sb mirrors it, written only from Stripe’s webhooks. | Property | Stripe field | Source of truth | | --- | --- | --- | | `amount` | `amount` | Stripe | ## Call it **Ask** ```text Reconcile the latest transaction. ``` **API** ```bash curl -X POST https://api.sb/kilnbakery.com/transactions/transaction_1/reconcile \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/kilnbakery.com", "transaction": { "$id": "https://api.sb/kilnbakery.com/transactions/transaction_1", "$type": "Transaction", "kind": "charge", "amount": { "amount": 9, "currency": "USD" } }, "action": { "$id": "https://api.sb/kilnbakery.com/actions/action_1", "operation": "Transaction.reconcile", "status": "done" }, "links": { "self": "https://api.sb/kilnbakery.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const transaction = await $.Transaction.reconcile({ transaction: 'transaction_1' }) ``` **CLI** ```bash npx startup-builder do Transaction.reconcile --json '{"transaction":"transaction_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Transaction.reconcile({ transaction: 'transaction_1' })" } } ``` ## Example A $49 Stripe charge is a Transaction. The monthly close reconciles it to two Entries. # reconcile URL: /business/nouns/transaction/reconcile · Id: `verb:Transaction.reconcile` · Call: `await $.Transaction.reconcile({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Reconcile matches a Transaction on a payment rail to the ledger Entries it settles. Reconcile matches a [Transaction](/business/nouns/transaction) on a payment rail to the ledger [Entries](/business/nouns/entry) it settles. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `transaction` | [Transaction](/business/nouns/transaction) | Yes | The Transaction to match. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `transaction` | [Transaction](/business/nouns/transaction) | Yes | The reconciled Transaction. | ## Effects - Emits [`Transaction.reconciled`](/business/events/Transaction.reconciled). - Performed by the [Finance Lead](/agents/finance/finance-lead). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Opens a Task when no Entry matches. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Transaction.reconcile](/business/nouns/transaction/reconcile) | | The record is not in a state that allows this Verb, so the call is refused. | [`refused`](/code/api/errors/refused) | Read the record, run the Verb that moves it to an allowed state, then retry. | [Transaction.reconcile](/business/nouns/transaction/reconcile) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Reconcile the latest transaction. ``` **API** ```bash curl -X POST https://api.sb/kilnbakery.com/transactions/transaction_1/reconcile \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/kilnbakery.com", "transaction": { "$id": "https://api.sb/kilnbakery.com/transactions/transaction_1", "$type": "Transaction", "kind": "charge", "amount": { "amount": 9, "currency": "USD" } }, "action": { "$id": "https://api.sb/kilnbakery.com/actions/action_1", "operation": "Transaction.reconcile", "status": "done" }, "links": { "self": "https://api.sb/kilnbakery.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const transaction = await $.Transaction.reconcile({ transaction: 'transaction_1' }) ``` **CLI** ```bash npx startup-builder do Transaction.reconcile --json '{"transaction":"transaction_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Transaction.reconcile({ transaction: 'transaction_1' })" } } ``` # Trigger URL: /business/nouns/trigger · Id: `noun:trigger` > A Trigger is what starts a Workflow: an Event, a schedule, or a Thing entering a state. A Trigger is what starts a [Workflow](/business/nouns/workflow): an [Event](/business/nouns/event), a schedule, or a [Thing](/business/nouns/thing) entering a state. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `event` | `string` | No | The Event selector it matches, such as `Order.placed`. | | `schedule` | `string` | No | A cadence or cron expression. | | `state` | `string` | No | The state whose entry fires it. | | `where` | `string` | No | The predicate an `event` Trigger matches, such as `choice = 'raise'`. | | `threshold` | `json` | No | A Metric staying below or above a value, optionally for a while, such as four weeks. | | `at` | `string` | No | When in its cadence a schedule runs, on the namespace’s clock, such as `mon 09:00`. | ## Object ```json { "$id": "https://api.sb/tutorloop.com/triggers/trigger_1", "$type": "Trigger", "event": "Example event", "schedule": "Example schedule", "state": "Example state", "where": "Example where", "threshold": {}, "at": "Example at" } ``` ## Relationships - A Trigger **fires on** many [Events](/business/nouns/event): a Trigger fires each time an [Event](/business/nouns/event) matching its selector happens. `firesOn`, inverse [`fires`](/business/nouns/event#rel-fires). - A Trigger **starts** many [Workflows](/business/nouns/workflow): when a Trigger fires, each [Workflow](/business/nouns/workflow) it starts runs as a new [Action](/business/nouns/action). `starts`, inverse [`startedBy`](/business/nouns/workflow#rel-started-by). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Trigger.create](/business/nouns/trigger/create) | Creates a Trigger. Inherited from [Noun](/business/nouns/noun). | None. | `Trigger.created` | Two-way: `try`, `send`, `do` | | [Trigger.get](/business/nouns/trigger/get) | Returns one Trigger by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Trigger.list](/business/nouns/trigger/list) | Returns Triggers, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Trigger.update](/business/nouns/trigger/update) | Changes the given properties of a Trigger. Inherited from [Noun](/business/nouns/noun). | None. | `Trigger.updated` | Two-way: `try`, `send`, `do` | | [Trigger.delete](/business/nouns/trigger/delete) | Deletes a Trigger; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Trigger.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Trigger.create` | Yes | Yes | Yes | No | | `Trigger.get` | Yes | Yes | Yes | Yes | | `Trigger.list` | Yes | Yes | Yes | Yes | | `Trigger.update` | Yes | Yes | Yes | No | | `Trigger.delete` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Add a trigger to QuietCopy. ``` **API** ```bash curl -X POST https://api.sb/quietcopy.com/triggers \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"event":"Example event"}' ``` ```json { "api": "https://api.sb/quietcopy.com", "trigger": { "$id": "https://api.sb/quietcopy.com/triggers/trigger_1", "$type": "Trigger", "event": "Example event", "schedule": "Example schedule" }, "action": { "$id": "https://api.sb/quietcopy.com/actions/action_1", "operation": "Trigger.create", "status": "done" }, "links": { "self": "https://api.sb/quietcopy.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const trigger = await $.Trigger.create({ event: 'Example event' }) ``` **CLI** ```bash npx startup-builder do Trigger.create --json '{"event":"Example event"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Trigger.create({ event: 'Example event' })" } } ``` ## Example The Event `Lead.created` is the Trigger of [Answer inbound](/workflows/processes/inbound-sales/answer-inbound). The schedule `0 9 * * 1` is the Trigger of the [Monday Role review](/workflows/processes/role-review/monday-role-review). # Variant URL: /business/nouns/variant · Id: `noun:variant` > A Variant is one value an Experiment can assign, such as a revision, a Price on a sibling Offer, or a prompt, with its lineage. A Variant is one value an [Experiment](/business/nouns/experiment) can assign, such as a revision, a [Price](/business/nouns/price) on a sibling [Offer](/business/nouns/offer), or a prompt, with its lineage. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `key` | `string` | Yes | The name the Flag returns for it. | | `value` | `json` | Yes | What it changes: copy, behavior, a definition Version, or a Thing. | | `control` | `boolean` | No | True for the current definition every challenger is judged against. | | `follows` | [Variant](/business/nouns/variant) | No | The Variant it was drafted from by a learn step. | ## Object ```json { "$id": "https://api.sb/shiftnote.app/variants/variant_1", "$type": "Variant", "key": "Example key", "value": {}, "control": true, "follows": "variant_1" } ``` ## Relationships - A Variant **has** many [Exposures](/business/nouns/exposure): the Variant the [Flag](/business/nouns/flag) assigned to this unit. `exposures`, inverse [`meets`](/business/nouns/exposure#rel-meets). - A Variant **is offered by** one [Experiment](/business/nouns/experiment): the Variants the [Experiment](/business/nouns/experiment) can assign, the control among them. `offeredBy`, inverse [`offers`](/business/nouns/experiment#rel-offers). - A Variant **is scored by** many [Readouts](/business/nouns/readout): the Variant the number describes. `scoredBy`, inverse [`scores`](/business/nouns/readout#rel-scores). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Variant.create](/business/nouns/variant/create) | Creates a Variant. Inherited from [Noun](/business/nouns/noun). | None. | `Variant.created` | Two-way: `try`, `send`, `do` | | [Variant.get](/business/nouns/variant/get) | Returns one Variant by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Variant.list](/business/nouns/variant/list) | Returns Variants, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Variant.update](/business/nouns/variant/update) | Changes the given properties of a Variant. Inherited from [Noun](/business/nouns/noun). | None. | `Variant.updated` | Two-way: `try`, `send`, `do` | | [Variant.delete](/business/nouns/variant/delete) | Deletes a Variant; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Variant.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Variant.create` | Yes | Yes | Yes | No | | `Variant.get` | Yes | Yes | Yes | Yes | | `Variant.list` | Yes | Yes | Yes | Yes | | `Variant.update` | Yes | Yes | Yes | No | | `Variant.delete` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Add a variant to RouteWise. ``` **API** ```bash curl -X POST https://api.sb/routewise.dev/variants \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"key":"Example key","value":{}}' ``` ```json { "api": "https://api.sb/routewise.dev", "variant": { "$id": "https://api.sb/routewise.dev/variants/variant_1", "$type": "Variant", "key": "Example key", "value": {} }, "action": { "$id": "https://api.sb/routewise.dev/actions/action_1", "operation": "Variant.create", "status": "done" }, "links": { "self": "https://api.sb/routewise.dev/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const variant = await $.Variant.create({ key: 'Example key', value: {} }) ``` **CLI** ```bash npx startup-builder do Variant.create --json '{"key":"Example key","value":{}}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Variant.create({ key: 'Example key', value: {} })" } } ``` ## Example A bakery tests two Variants of its pickup button behind one [Flag](/business/nouns/flag): the control reads `Pick up today`, and the challenger reads `Hold my loaf`. The challenger follows the control. # Verb URL: /business/nouns/verb · Id: `noun:verb` > A Verb is an action an Agent or a person performs on a Noun, emitting one event when it completes. A Verb is an action an [Agent](/business/nouns/agent) or a [Human](/business/nouns/human) performs on a [Noun](/business/nouns/noun), emitting one [Event](/business/nouns/event) when it completes. Its name is `Noun.verb`, and its Event is the past tense: `Offer.publish` emits `Offer.published`. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `name` | `string` | Yes | The camelCase action form. | | `event` | `string` | Yes | The event the Verb emits. | | `publishedIn` | [Version](/business/nouns/version) | No | The first published Version that serves it; from then on, edits go through a Change and `delete` refuses. | | `status` | `string` | Yes | One of `draft`, `published` or `retired`. | ## Object ```json { "$id": "https://api.sb/patentpad.com/verbs/verb_1", "$type": "Verb", "name": "PatentPad", "event": "Example event", "publishedIn": "version_1", "status": "draft" } ``` ## Relationships - A Verb **acts on** one [Noun](/business/nouns/noun): every Verb acts on one [Noun](/business/nouns/noun), which names it: `Startup.launch` acts on [Startup](/business/nouns/startup). `actsOn`, inverse [`actedOnBy`](/business/nouns/noun#rel-acted-on-by). - A Verb **is allowed by** many [Permissions](/business/nouns/permission): each [Permission](/business/nouns/permission) allows one Verb, within its scope and [Limit](/business/nouns/limit). `allowedBy`, inverse [`allows`](/business/nouns/permission#rel-allows). - A Verb **defaults to** one [Mode](/business/nouns/mode): the [Mode](/business/nouns/mode) a call uses when the caller names none: `try`, `send` or `do`. `defaultsTo`, inverse [`defaultFor`](/business/nouns/mode#rel-default-for). - A Verb **is exposed as** many [Tools](/business/nouns/tool): a [Tool](/business/nouns/tool) is one Verb under one name on every [Interface](/business/nouns/interface), such as `Contact.create`. `exposedAs`, inverse [`exposes`](/business/nouns/tool#rel-exposes). - A Verb **is graded by** many [Evaluators](/business/nouns/evaluator): the Verbs whose results the [Evaluator](/business/nouns/evaluator) scores against its rubric before they count as done. `gradedBy`, inverse [`grades`](/business/nouns/evaluator#rel-grades). - A Verb **is implemented by** many [Functions](/business/nouns/function): a [Function](/business/nouns/function) is how a Verb runs: code, a generative model, an [Agent](/business/nouns/agent) or a [Human](/business/nouns/human), and the caller never sees which. `implementedBy`, inverse [`implements`](/business/nouns/function#rel-implements). - A Verb **is invoked as** many [Actions](/business/nouns/action): each [Action](/business/nouns/action) performs one Verb, which fixes its inputs, the [Event](/business/nouns/event) it emits and its delay window. `invokedAs`, inverse [`invokes`](/business/nouns/action#rel-invokes). - A Verb **is reserved by** many [Reserved Acts](/business/nouns/reserved-act): the Verb the law reserves to a credentialed [Human](/business/nouns/human) in the act’s jurisdiction. `reservedBy`, inverse [`reserves`](/business/nouns/reserved-act#rel-reserves). - A Verb **types** many [Relationships](/business/nouns/relationship): a [Relationship](/business/nouns/relationship) reads through a Verb whose forms name it from each side, such as `makes` and `madeBy`. `types`, inverse [`typedBy`](/business/nouns/relationship#rel-typed-by). ## Lifecycle | State | Meaning | Moves to | | --- | --- | --- | | `draft` (first) | Defined and editable; no published Version serves it. | `published` on [`Version.deployed`](/business/events/Version.deployed) when the deployed Version is the first to include this Verb | | `published` | A published Version serves it; edits go through a Change, and `delete` refuses. | `retired` by [Verb.retire](/business/nouns/verb/retire) | | `retired` | New Versions leave it out; callers pinned to earlier Versions keep calling it. | None: it ends here. | ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Verb.retire](/business/nouns/verb/retire) | Retire removes a published Verb from new Versions; callers pinned to earlier Versions keep calling it. | [Product Lead](/agents/product/product-lead) | [`Verb.retired`](/business/events/Verb.retired) | One-way (customer): `send`, `do` | | [Verb.create](/business/nouns/verb/create) | Creates a Verb. Inherited from [Noun](/business/nouns/noun). | None. | `Verb.created` | Two-way: `try`, `send`, `do` | | [Verb.get](/business/nouns/verb/get) | Returns one Verb by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Verb.list](/business/nouns/verb/list) | Returns Verbs, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Verb.update](/business/nouns/verb/update) | Changes the given properties of a Verb. Inherited from [Noun](/business/nouns/noun). | None. | `Verb.updated` | Two-way: `try`, `send`, `do` | | [Verb.delete](/business/nouns/verb/delete) | Deletes a Verb; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Verb.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Verb.create` | Yes | Yes | Yes | No | | `Verb.get` | Yes | Yes | Yes | Yes | | `Verb.list` | Yes | Yes | Yes | Yes | | `Verb.update` | Yes | Yes | Yes | No | | `Verb.delete` | Yes | Yes | Yes | No | | `Verb.retire` | Yes | No | No | No | ## Call it **Ask** ```text Retire the latest verb. ``` **API** ```bash curl -X POST https://api.sb/kilnbakery.com/verbs/verb_1/retire \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/kilnbakery.com", "version": { "$id": "https://api.sb/kilnbakery.com/versions/version_1", "$type": "Version", "fingerprint": "sha256:9f2c4e1a7b3d" }, "verb": { "$id": "https://api.sb/kilnbakery.com/verbs/verb_1", "$type": "Verb", "name": "Kiln Bakery", "event": "Example event", "status": "retired" }, "action": { "$id": "https://api.sb/kilnbakery.com/actions/action_1", "operation": "Verb.retire", "status": "done" }, "links": { "self": "https://api.sb/kilnbakery.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { version, verb } = await $.Verb.retire({ verb: 'verb_1' }) ``` **CLI** ```bash npx startup-builder do Verb.retire --json '{"verb":"verb_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Verb.retire({ verb: 'verb_1' })" } } ``` ## Example An Agent runs [`Offer.publish`](/business/nouns/offer/publish) on a $49-a-month contract-review [Offer](/business/nouns/offer). The run is one [Action](/business/nouns/action): the Offer opens for acceptance, and `Offer.published` records the moment. # retire URL: /business/nouns/verb/retire · Id: `verb:Verb.retire` · Call: `await $.Verb.retire({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Retire removes a published Verb from new Versions; callers pinned to earlier Versions keep calling it. Retire removes a published [Verb](/business/nouns/verb) from new [Versions](/business/nouns/version); callers pinned to earlier Versions keep calling it. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `verb` | [Verb](/business/nouns/verb) | Yes | The Verb to retire. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `version` | [Version](/business/nouns/version) | Yes | The new Version, without the Verb. | | `verb` | [Verb](/business/nouns/verb) | Yes | The Verb, now retired from new Versions. | ## Effects - Emits [`Verb.retired`](/business/events/Verb.retired). - Performed by the [Product Lead](/agents/product/product-lead). - One-way (customer): it waits out its delay window, and runs in the `send` and `do` modes. - Opens a new Version without the Verb through a Change. - Keeps every pinned Version answering it. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Verb.retire](/business/nouns/verb/retire) | ## When it waits | Gate | Default | | --- | --- | | Decision class | High: one-way, broad (customer) | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | 1 business day, in which a watcher can pause, redirect or cancel it; then it runs. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Retire the latest verb. ``` **API** ```bash curl -X POST https://api.sb/kilnbakery.com/verbs/verb_1/retire \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/kilnbakery.com", "version": { "$id": "https://api.sb/kilnbakery.com/versions/version_1", "$type": "Version", "fingerprint": "sha256:9f2c4e1a7b3d" }, "verb": { "$id": "https://api.sb/kilnbakery.com/verbs/verb_1", "$type": "Verb", "name": "Kiln Bakery", "event": "Example event", "status": "retired" }, "action": { "$id": "https://api.sb/kilnbakery.com/actions/action_1", "operation": "Verb.retire", "status": "done" }, "links": { "self": "https://api.sb/kilnbakery.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { version, verb } = await $.Verb.retire({ verb: 'verb_1' }) ``` **CLI** ```bash npx startup-builder do Verb.retire --json '{"verb":"verb_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Verb.retire({ verb: 'verb_1' })" } } ``` # deploy URL: /business/nouns/version/deploy · Id: `verb:Version.deploy` · Call: `await $.Version.deploy({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Deploy points a Startup’s live address at a Version, so every Interface serves that build. Deploy points a [Startup](/business/nouns/startup)’s live address at a [Version](/business/nouns/version), so every [Interface](/business/nouns/interface) serves that build. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `version` | [Version](/business/nouns/version) | Yes | The Version to serve. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `version` | [Version](/business/nouns/version) | Yes | The Version, now live. | ## Effects - Emits [`Version.deployed`](/business/events/Version.deployed). - Performed by the [Engineering Lead](/agents/engineering/engineering-lead). - Keeps the previous Version, so a `revert` restores it. - At a share of 100, resolves every Issue whose last open Change this Version carries. - Refuses `live` when a Secret a Function declares is missing in `live`. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Version.deploy](/business/nouns/version/deploy) | | The record is not in a state that allows this Verb, so the call is refused. | [`refused`](/code/api/errors/refused) | Read the record, run the Verb that moves it to an allowed state, then retry. | [Version.deploy](/business/nouns/version/deploy) | | `live` when a Secret a Function declares is missing in `live` | [`refused`](/code/api/errors/refused) | Clear what the check names, then call it again. | [Version.deploy](/business/nouns/version/deploy) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Medium: two-way, visible | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | 1 business hour, in which a watcher can pause, redirect or cancel it; then it runs. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Deploy the latest version. ``` **API** ```bash curl -X POST https://api.sb/patentpad.com/versions/version_1/deploy \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/patentpad.com", "version": { "$id": "https://api.sb/patentpad.com/versions/version_1", "$type": "Version", "fingerprint": "sha256:9f2c4e1a7b3d" }, "action": { "$id": "https://api.sb/patentpad.com/actions/action_1", "operation": "Version.deploy", "status": "done" }, "links": { "self": "https://api.sb/patentpad.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const version = await $.Version.deploy({ version: 'version_1' }) ``` **CLI** ```bash npx startup-builder do Version.deploy --json '{"version":"version_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Version.deploy({ version: 'version_1' })" } } ``` Guides that call it: [Ship my changes](/code/ship-my-changes). # Version URL: /business/nouns/version · Id: `noun:version` > A Version is an immutable build of a definition at a fingerprint; an Order keeps the Offer Version it bought. A Version is an immutable build of a definition at a fingerprint; an [Order](/business/nouns/order) keeps the [Offer](/business/nouns/offer) Version it bought. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `fingerprint` | `string` | Yes | The content hash that identifies the build. | ## Object ```json { "$id": "https://api.sb/quietcopy.com/versions/version_1", "$type": "Version", "fingerprint": "sha256:9f2c4e1a7b3d" } ``` ## Relationships - A Version **is pinned cohorts** many [Cohorts](/business/nouns/cohort): every [Startup](/business/nouns/startup) in a [Cohort](/business/nouns/cohort) runs the same Version of a shared definition; a control Cohort keeps the prior one. `pinnedCohorts`, inverse [`pinnedTo`](/business/nouns/cohort#rel-pinned-to). - A Version **is a version of** one [Thing](/business/nouns/thing): every published change to a [Thing](/business/nouns/thing)’s definition is an immutable Version, kept forever. `versionOf`, inverse [`versionedAs`](/business/nouns/thing#rel-versioned-as). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Version.deploy](/business/nouns/version/deploy) | Deploy points a Startup’s live address at a Version, so every Interface serves that build. | [Engineering Lead](/agents/engineering/engineering-lead) | [`Version.deployed`](/business/events/Version.deployed) | None. | | [Version.get](/business/nouns/version/get) | Returns one Version by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Version.list](/business/nouns/version/list) | Returns Versions, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | A Version is kept forever and never edited: it has no `update` or `delete`. ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Version.get` | Yes | Yes | Yes | Yes | | `Version.list` | Yes | Yes | Yes | Yes | | `Version.deploy` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Deploy the latest version. ``` **API** ```bash curl -X POST https://api.sb/patentpad.com/versions/version_1/deploy \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/patentpad.com", "version": { "$id": "https://api.sb/patentpad.com/versions/version_1", "$type": "Version", "fingerprint": "sha256:9f2c4e1a7b3d" }, "action": { "$id": "https://api.sb/patentpad.com/actions/action_1", "operation": "Version.deploy", "status": "done" }, "links": { "self": "https://api.sb/patentpad.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const version = await $.Version.deploy({ version: 'version_1' }) ``` **CLI** ```bash npx startup-builder do Version.deploy --json '{"version":"version_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Version.deploy({ version: 'version_1' })" } } ``` ## Example A dental group's [Order](/business/nouns/order) points to Version 3 of the $99 [Offer](/business/nouns/offer). Version 4 raises the [Price](/business/nouns/price) to $119, and the Order keeps Version 3. # draft URL: /business/nouns/video/draft · Id: `verb:Video.draft` · Call: `await $.Video.draft({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Draft writes a Video’s timeline from a Startup’s records, its Brand and a Template, with a draft mark on every frame. Draft writes a [Video](/business/nouns/video)’s timeline from a [Startup](/business/nouns/startup)’s records, its [Brand](/business/nouns/brand) and a [Template](/business/nouns/template), with a draft mark on every frame. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `brand` | [Brand](/business/nouns/brand) | Yes | The Brand the Video speaks for. | | `offer` | [Offer](/business/nouns/offer) | No | The Offer the Video presents. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `video` | [Video](/business/nouns/video) | Yes | The drafted Video, in status `Draft`. | ## Effects - Emits [`Video.drafted`](/business/events/Video.drafted). - Performed by the [Video Producer](/agents/marketing/video-producer). - Every claim on screen links to the record it reads. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Video.draft](/business/nouns/video/draft) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Draft the latest video with a brand. ``` **API** ```bash curl -X POST https://api.sb/petpantry.shop/videos/draft \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"brand":"brand_1"}' ``` ```json { "api": "https://api.sb/petpantry.shop", "video": { "$id": "https://api.sb/petpantry.shop/videos/video_1", "$type": "Video", "status": "Draft", "timeline": {}, "brand": "brand_1" }, "action": { "$id": "https://api.sb/petpantry.shop/actions/action_1", "operation": "Video.draft", "status": "done" }, "links": { "self": "https://api.sb/petpantry.shop/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const video = await $.Video.draft({ brand: 'brand_1' }) ``` **CLI** ```bash npx startup-builder do Video.draft --json '{"brand":"brand_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Video.draft({ brand: 'brand_1' })" } } ``` # finalize URL: /business/nouns/video/finalize · Id: `verb:Video.finalize` · Call: `await $.Video.finalize({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Finalize lifts a Video’s draft mark once every claim it makes reads from a live record, so its cuts can be published. Finalize lifts a [Video](/business/nouns/video)’s draft mark once every claim it makes reads from a live record, so its cuts can be published. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `video` | [Video](/business/nouns/video) | Yes | The rendered Video to finalize. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `video` | [Video](/business/nouns/video) | Yes | The Video, in status `Final`. | ## Effects - Emits [`Video.finalized`](/business/events/Video.finalized). - Performed by the [Video Producer](/agents/marketing/video-producer). - A Video with an unsettled claim keeps status `Draft` and cannot be published. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Video.finalize](/business/nouns/video/finalize) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Finalize the latest video. ``` **API** ```bash curl -X POST https://api.sb/routewise.dev/videos/video_1/finalize \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/routewise.dev", "video": { "$id": "https://api.sb/routewise.dev/videos/video_1", "$type": "Video", "status": "Draft", "timeline": {}, "brand": "brand_1" }, "action": { "$id": "https://api.sb/routewise.dev/actions/action_1", "operation": "Video.finalize", "status": "done" }, "links": { "self": "https://api.sb/routewise.dev/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const video = await $.Video.finalize({ video: 'video_1' }) ``` **CLI** ```bash npx startup-builder do Video.finalize --json '{"video":"video_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Video.finalize({ video: 'video_1' })" } } ``` # Video URL: /business/nouns/video · Id: `noun:video` > A Video is a timed composition held as data: a timeline of scenes and spoken lines, drafted from records and rendered per format. A Video is a timed composition held as data: a timeline of scenes and spoken lines, drafted from records and rendered per format. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `status` | `string` | Yes | One of `Draft`, `Rendered`, `Final`, or `Superseded`. | | `timeline` | `json` | Yes | The ordered scenes on a fixed grid, the only timing truth for picture, voice and captions. | | `brand` | [Brand](/business/nouns/brand) | Yes | The Brand whose voice, palette and type the Video uses. | | `offer` | [Offer](/business/nouns/offer) | No | The Offer the Video presents, when it presents one. | ## Object ```json { "$id": "https://api.sb/routewise.dev/videos/video_1", "$type": "Video", "status": "Draft", "timeline": {}, "brand": "brand_1", "offer": "offer_1" } ``` ## Relationships None. ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Video.draft](/business/nouns/video/draft) | Draft writes a Video’s timeline from a Startup’s records, its Brand and a Template, with a draft mark on every frame. | [Video Producer](/agents/marketing/video-producer) | [`Video.drafted`](/business/events/Video.drafted) | None. | | [Video.finalize](/business/nouns/video/finalize) | Finalize lifts a Video’s draft mark once every claim it makes reads from a live record, so its cuts can be published. | [Video Producer](/agents/marketing/video-producer) | [`Video.finalized`](/business/events/Video.finalized) | None. | | [Video.create](/business/nouns/video/create) | Creates a Video. Inherited from [Noun](/business/nouns/noun). | None. | `Video.created` | Two-way: `try`, `send`, `do` | | [Video.get](/business/nouns/video/get) | Returns one Video by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Video.list](/business/nouns/video/list) | Returns Videos, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Video.update](/business/nouns/video/update) | Changes the given properties of a Video. Inherited from [Noun](/business/nouns/noun). | None. | `Video.updated` | Two-way: `try`, `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Video.create` | Yes | Yes | Yes | No | | `Video.get` | Yes | Yes | Yes | Yes | | `Video.list` | Yes | Yes | Yes | Yes | | `Video.update` | Yes | Yes | Yes | No | | `Video.draft` | Yes | Yes | Yes | No | | `Video.finalize` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Draft the latest video with a brand. ``` **API** ```bash curl -X POST https://api.sb/petpantry.shop/videos/draft \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"brand":"brand_1"}' ``` ```json { "api": "https://api.sb/petpantry.shop", "video": { "$id": "https://api.sb/petpantry.shop/videos/video_1", "$type": "Video", "status": "Draft", "timeline": {}, "brand": "brand_1" }, "action": { "$id": "https://api.sb/petpantry.shop/actions/action_1", "operation": "Video.draft", "status": "done" }, "links": { "self": "https://api.sb/petpantry.shop/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const video = await $.Video.draft({ brand: 'brand_1' }) ``` **CLI** ```bash npx startup-builder do Video.draft --json '{"brand":"brand_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Video.draft({ brand: 'brand_1' })" } } ``` ## Example A home-workout app drafts a 30-second Video from a timeline of clips and a script. Once its captions and loudness checks pass, `Video.finalize` renders cuts for vertical and square formats. # Visit URL: /business/nouns/visit · Id: `noun:visit` > A Visit is one span of a Visitor’s Events on a Startup’s Sites and Apps. A Visit is one span of a [Visitor](/business/nouns/visitor)’s [Events](/business/nouns/event) on a [Startup](/business/nouns/startup)’s [Sites](/business/nouns/site) and [Apps](/business/nouns/app). ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `startedAt` | `datetime` | Yes | When it began. | | `acquisition` | `string` | No | How the Visitor arrived: search, AI answer, agent, referral, ad, or direct. | ## Object ```json { "$id": "https://api.sb/routewise.dev/visits/visit_1", "$type": "Visit", "startedAt": "2026-10-22T12:00:00Z", "acquisition": "Example acquisition" } ``` ## Relationships - A Visit **lands** one [Site](/business/nouns/site): each Visit arrives on one [Site](/business/nouns/site). `lands`, inverse [`visits`](/business/nouns/site#rel-visits). - A Visit **has** one [Recording](/business/nouns/recording): a [Recording](/business/nouns/recording) replays one Visit, linked from every funnel step that Visit reached. `recording`, inverse [`replays`](/business/nouns/recording#rel-replays). - A Visit **is started by** one [Visitor](/business/nouns/visitor): each Visit is one span of a [Visitor](/business/nouns/visitor)’s [Events](/business/nouns/event) on the [Startup](/business/nouns/startup)’s [Sites](/business/nouns/site) and [Apps](/business/nouns/app). `startedBy`, inverse [`starts`](/business/nouns/visitor#rel-starts). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Visit.get](/business/nouns/visit/get) | Returns one Visit by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Visit.list](/business/nouns/visit/list) | Returns Visits, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | A Visit is kept forever and never edited: it has no `update` or `delete`. ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Visit.get` | Yes | Yes | Yes | Yes | | `Visit.list` | Yes | Yes | Yes | Yes | ## Call it **Ask** ```text Show me the latest visit. ``` **API** ```bash curl https://api.sb/ledgerlark.com/visits/visit_1 \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/ledgerlark.com", "$type": "Visit", "$id": "https://api.sb/ledgerlark.com/visits/visit_1", "visit": { "$id": "https://api.sb/ledgerlark.com/visits/visit_1", "$type": "Visit", "startedAt": "2026-10-22T12:00:00Z" }, "links": { "self": "https://api.sb/ledgerlark.com/visits/visit_1", "up": "https://api.sb/ledgerlark.com/visits" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const visit = await $.Visit.get({ id: 'visit_1' }) ``` **CLI** ```bash npx startup-builder do Visit.get --json '{"id":"visit_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Visit.get({ id: 'visit_1' })" } } ``` ## Example A Visitor lands on the pricing [Page](/business/nouns/page), reads the docs, and leaves after 4 minutes. Those Events form one Visit. # forget URL: /business/nouns/visitor/forget · Id: `verb:Visitor.forget` · Call: `await $.Visitor.forget({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Forget masks a person’s captured data across every Event and Recording and suppresses further capture, keeping the records. Forget masks a person’s captured data across every [Event](/business/nouns/event) and [Recording](/business/nouns/recording) and suppresses further capture, keeping the records. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `visitor` | [Visitor](/business/nouns/visitor) | Yes | The Visitor to forget. | | `request` | `text` | Yes | The privacy request it answers. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `visitor` | [Visitor](/business/nouns/visitor) | Yes | The Visitor, masked. | ## Effects - Emits [`Visitor.forgotten`](/business/events/Visitor.forgotten). - Performed by the [Privacy Officer](/agents/legal/privacy-officer). - One-way (customer): it waits out its delay window, and runs in the `send` and `do` modes. - Masks identifying fields in place; records are kept forever and nothing is erased. - Stops capture for the person on every Domain the Startup serves. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Visitor.forget](/business/nouns/visitor/forget) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Medium: one-way, bounded (customer) | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | 1 business hour, in which a watcher can pause, redirect or cancel it; then it runs. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Forget the latest visitor. ``` **API** ```bash curl -X POST https://api.sb/routewise.dev/visitors/visitor_1/forget \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"request":"Example request"}' ``` ```json { "api": "https://api.sb/routewise.dev", "visitor": { "$id": "https://api.sb/routewise.dev/visitors/visitor_1", "$type": "Visitor", "firstSeenAt": "2026-10-22T12:00:00Z" }, "action": { "$id": "https://api.sb/routewise.dev/actions/action_1", "operation": "Visitor.forget", "status": "done" }, "links": { "self": "https://api.sb/routewise.dev/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const visitor = await $.Visitor.forget({ visitor: 'visitor_1', request: 'Example request' }) ``` **CLI** ```bash npx startup-builder do Visitor.forget --json '{"visitor":"visitor_1","request":"Example request"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Visitor.forget({ visitor: 'visitor_1', request: 'Example request' })" } } ``` # identify URL: /business/nouns/visitor/identify · Id: `verb:Visitor.identify` · Call: `await $.Visitor.identify({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Identify joins a Visitor to the Contact it turns out to be, so earlier Visits count toward that person. Identify joins a [Visitor](/business/nouns/visitor) to the [Contact](/business/nouns/contact) it turns out to be, so earlier [Visits](/business/nouns/visit) count toward that person. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `visitor` | [Visitor](/business/nouns/visitor) | Yes | The Visitor. | | `contact` | [Contact](/business/nouns/contact) | Yes | The Contact or Customer the Visitor is. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `contact` | [Contact](/business/nouns/contact) | Yes | The Contact, with the Visitor’s Visits attached. | | `visitor` | [Visitor](/business/nouns/visitor) | Yes | The Visitor, now joined to its Contact. | ## Effects - Emits [`Visitor.identified`](/business/events/Visitor.identified). - Performed by the [Analyst](/agents/marketing/analyst). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Runs at sign-up, sign-in and checkout without a call. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Visitor.identify](/business/nouns/visitor/identify) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Identify the latest visitor with a contact. ``` **API** ```bash curl -X POST https://api.sb/petpantry.shop/visitors/visitor_1/identify \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"contact":"contact_1"}' ``` ```json { "api": "https://api.sb/petpantry.shop", "contact": { "$id": "https://api.sb/petpantry.shop/contacts/contact_1", "$type": "Contact", "email": "lena@petpantry.shop", "phone": "Example phone" }, "visitor": { "$id": "https://api.sb/petpantry.shop/visitors/visitor_1", "$type": "Visitor", "firstSeenAt": "2026-10-22T12:00:00Z" }, "action": { "$id": "https://api.sb/petpantry.shop/actions/action_1", "operation": "Visitor.identify", "status": "done" }, "links": { "self": "https://api.sb/petpantry.shop/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { contact, visitor } = await $.Visitor.identify({ visitor: 'visitor_1', contact: 'contact_1' }) ``` **CLI** ```bash npx startup-builder do Visitor.identify --json '{"visitor":"visitor_1","contact":"contact_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Visitor.identify({ visitor: 'visitor_1', contact: 'contact_1' })" } } ``` # Visitor URL: /business/nouns/visitor · Id: `noun:visitor` > A Visitor is someone a Startup cannot name, known by an id scoped to that Startup. A Visitor is someone a [Startup](/business/nouns/startup) cannot name, known by an id scoped to that Startup. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `firstSeenAt` | `datetime` | Yes | When the first request arrived. | ## Object ```json { "$id": "https://api.sb/kilnbakery.com/visitors/visitor_1", "$type": "Visitor", "firstSeenAt": "2026-10-22T12:00:00Z" } ``` ## Relationships - A Visitor **is identified as** one [Lead](/business/nouns/lead): a [Lead](/business/nouns/lead), once it gives an address, is tied to every Visitor id it used, one per device. `identifiedAs`, inverse [`identifies`](/business/nouns/lead#rel-identifies). - A Visitor **starts** many [Visits](/business/nouns/visit): each [Visit](/business/nouns/visit) is one span of a Visitor’s [Events](/business/nouns/event) on the [Startup](/business/nouns/startup)’s [Sites](/business/nouns/site) and [Apps](/business/nouns/app). `starts`, inverse [`startedBy`](/business/nouns/visit#rel-started-by). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Visitor.forget](/business/nouns/visitor/forget) | Forget masks a person’s captured data across every Event and Recording and suppresses further capture, keeping the records. | [Privacy Officer](/agents/legal/privacy-officer) | [`Visitor.forgotten`](/business/events/Visitor.forgotten) | One-way (customer): `send`, `do` | | [Visitor.identify](/business/nouns/visitor/identify) | Identify joins a Visitor to the Contact it turns out to be, so earlier Visits count toward that person. | [Analyst](/agents/marketing/analyst) | [`Visitor.identified`](/business/events/Visitor.identified) | Two-way: `try`, `send`, `do` | | [Visitor.merge](/business/nouns/visitor/merge) | Merge joins two Visitor ids that belong to one person and keeps both as aliases. | [Analyst](/agents/marketing/analyst) | [`Visitor.merged`](/business/events/Visitor.merged) | Two-way: `try`, `send`, `do` | | [Visitor.create](/business/nouns/visitor/create) | Creates a Visitor. Inherited from [Noun](/business/nouns/noun). | None. | `Visitor.created` | Two-way: `try`, `send`, `do` | | [Visitor.get](/business/nouns/visitor/get) | Returns one Visitor by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Visitor.list](/business/nouns/visitor/list) | Returns Visitors, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Visitor.update](/business/nouns/visitor/update) | Changes the given properties of a Visitor. Inherited from [Noun](/business/nouns/noun). | None. | `Visitor.updated` | Two-way: `try`, `send`, `do` | | [Visitor.delete](/business/nouns/visitor/delete) | Deletes a Visitor; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Visitor.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Visitor.create` | Yes | Yes | Yes | No | | `Visitor.get` | Yes | Yes | Yes | Yes | | `Visitor.list` | Yes | Yes | Yes | Yes | | `Visitor.update` | Yes | Yes | Yes | No | | `Visitor.delete` | Yes | Yes | Yes | No | | `Visitor.forget` | Yes | No | No | No | | `Visitor.identify` | Yes | Yes | Yes | No | | `Visitor.merge` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Identify the latest visitor with a contact. ``` **API** ```bash curl -X POST https://api.sb/petpantry.shop/visitors/visitor_1/identify \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"contact":"contact_1"}' ``` ```json { "api": "https://api.sb/petpantry.shop", "contact": { "$id": "https://api.sb/petpantry.shop/contacts/contact_1", "$type": "Contact", "email": "lena@petpantry.shop", "phone": "Example phone" }, "visitor": { "$id": "https://api.sb/petpantry.shop/visitors/visitor_1", "$type": "Visitor", "firstSeenAt": "2026-10-22T12:00:00Z" }, "action": { "$id": "https://api.sb/petpantry.shop/actions/action_1", "operation": "Visitor.identify", "status": "done" }, "links": { "self": "https://api.sb/petpantry.shop/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { contact, visitor } = await $.Visitor.identify({ visitor: 'visitor_1', contact: 'contact_1' }) ``` **CLI** ```bash npx startup-builder do Visitor.identify --json '{"visitor":"visitor_1","contact":"contact_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Visitor.identify({ visitor: 'visitor_1', contact: 'contact_1' })" } } ``` ## Example Someone reads the pricing [Page](/business/nouns/page) of a meal-planning [App](/business/nouns/app) without signing in. The Visitor is known only as `v_8f2c`, an id no sibling Startup sees. # merge URL: /business/nouns/visitor/merge · Id: `verb:Visitor.merge` · Call: `await $.Visitor.merge({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Merge joins two Visitor ids that belong to one person and keeps both as aliases. Merge joins two [Visitor](/business/nouns/visitor) ids that belong to one person and keeps both as aliases. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `visitor` | [Visitor](/business/nouns/visitor) | Yes | The Visitor to merge. | | `into` | [Visitor](/business/nouns/visitor) | Yes | The Visitor that remains. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `visitor` | [Visitor](/business/nouns/visitor) | Yes | The remaining Visitor. | ## Effects - Emits [`Visitor.merged`](/business/events/Visitor.merged). - Performed by the [Analyst](/agents/marketing/analyst). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Events never move or change; reads follow the alias. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Visitor.merge](/business/nouns/visitor/merge) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Merge the latest visitor. ``` **API** ```bash curl -X POST https://api.sb/quietcopy.com/visitors/visitor_1/merge \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"into":"visitor_1"}' ``` ```json { "api": "https://api.sb/quietcopy.com", "visitor": { "$id": "https://api.sb/quietcopy.com/visitors/visitor_1", "$type": "Visitor", "firstSeenAt": "2026-10-22T12:00:00Z" }, "action": { "$id": "https://api.sb/quietcopy.com/actions/action_1", "operation": "Visitor.merge", "status": "done" }, "links": { "self": "https://api.sb/quietcopy.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const visitor = await $.Visitor.merge({ visitor: 'visitor_1', into: 'visitor_1' }) ``` **CLI** ```bash npx startup-builder do Visitor.merge --json '{"visitor":"visitor_1","into":"visitor_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Visitor.merge({ visitor: 'visitor_1', into: 'visitor_1' })" } } ``` # clone URL: /business/nouns/voice/clone · Id: `verb:Voice.clone` · Call: `await $.Voice.clone({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Clone trains a Voice from a real speaker’s recordings after the speaker records Consent in that same voice. Clone trains a [Voice](/business/nouns/voice) from a real speaker’s recordings after the speaker records [Consent](/business/nouns/consent) in that same voice. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `speaker` | [Person](/business/nouns/person) | Yes | The person whose voice it is. | | `samples` | list of [File](/business/nouns/file) | Yes | Recordings of the speaker. | | `consent` | [Consent](/business/nouns/consent) | Yes | The speaker’s Consent, spoken in the voice being cloned. | | `scope` | `string` | Yes | Who may speak in it. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `voice` | [Voice](/business/nouns/voice) | Yes | The Voice, `training` until the upstream finishes. | ## Effects - Emits [`Voice.cloned`](/business/events/Voice.cloned). - Performed by the [Content Lead](/agents/marketing/content-lead). - Two-way: it runs at once, in the `try`, `send` and `do` modes. - Refuses when the Consent is missing, withdrawn, or not spoken by the speaker. - Moves the Voice to `ready` when training ends. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Voice.clone](/business/nouns/voice/clone) | | The Consent is missing, withdrawn, or not spoken by the speaker | [`refused`](/code/api/errors/refused) | Clear what the check names, then call it again. | [Voice.clone](/business/nouns/voice/clone) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Clone the latest voice with a person and a file and consent. ``` **API** ```bash curl -X POST https://api.sb/ledgerlark.com/voices/clone \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"speaker":"person_1","samples":["file_1"],"consent":"consent_1","scope":"studio"}' ``` ```json { "api": "https://api.sb/ledgerlark.com", "voice": { "$id": "https://api.sb/ledgerlark.com/voices/voice_1", "$type": "Voice", "origin": "cloned", "scope": "studio", "status": "training" }, "action": { "$id": "https://api.sb/ledgerlark.com/actions/action_1", "operation": "Voice.clone", "status": "done" }, "links": { "self": "https://api.sb/ledgerlark.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const voice = await $.Voice.clone({ speaker: 'person_1', samples: ['file_1'], consent: 'consent_1', scope: 'studio' }) ``` **CLI** ```bash npx startup-builder do Voice.clone --json '{"speaker":"person_1","samples":["file_1"],"consent":"consent_1","scope":"studio"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Voice.clone({ speaker: 'person_1', samples: ['file_1'], consent: 'consent_1', scope: 'studio' })" } } ``` # Voice URL: /business/nouns/voice · Id: `noun:voice` > A Voice is a reusable synthetic speaking voice, cloned from a consenting speaker or designed from a description, that speech Files are rendered in. A Voice is a reusable synthetic speaking voice, cloned from a consenting speaker or designed from a description, that speech [Files](/business/nouns/file) are rendered in. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `origin` | `string` | Yes | `cloned` from a real speaker’s recordings, or `designed` from a description and sounding like no real person. | | `speaker` | [Person](/business/nouns/person) | No | The real person a cloned Voice sounds like. | | `consent` | [Consent](/business/nouns/consent) | No | The speaker’s Consent, recorded in that voice, naming the Startup and the uses allowed; required for a cloned Voice. Never randomized. | | `scope` | `string` | Yes | Who may speak in it: every sibling, one Startup, or one Customer. | | `samples` | list of [File](/business/nouns/file) | No | The recordings it was trained from, kept forever. | | `status` | `string` | Yes | `training` until the upstream finishes, `ready` for speech, `retired` once its trained copy is deleted. | ## Object ```json { "$id": "https://api.sb/kilnbakery.com/voices/voice_1", "$type": "Voice", "origin": "cloned", "speaker": "person_1", "consent": "consent_1", "scope": "studio", "samples": [ "file_1" ], "status": "training" } ``` ## Relationships - A Voice **sounds like** one [Person](/business/nouns/person): a cloned Voice sounds like one real person, and exists only while that person’s [Consent](/business/nouns/consent) holds. `soundsLike`, inverse [`voices`](/business/nouns/person#rel-voices). ## Lifecycle | State | Meaning | Moves to | | --- | --- | --- | | `training` (first) | The upstream is training it from the speaker’s recordings. | `ready` on [`Voice.trained`](/business/nouns/voice#voicetrained); `retired` by [Voice.retire](/business/nouns/voice/retire) | | `ready` | Speech Files render in it, within its scope. | `retired` by [Voice.retire](/business/nouns/voice/retire) | | `retired` | Its trained copy is deleted at the upstream; its record and every File made in it stay. | None: it ends here. | ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Voice.clone](/business/nouns/voice/clone) | Clone trains a Voice from a real speaker’s recordings after the speaker records Consent in that same voice. | [Content Lead](/agents/marketing/content-lead) | [`Voice.cloned`](/business/events/Voice.cloned) | Two-way: `try`, `send`, `do` | | [Voice.retire](/business/nouns/voice/retire) | Retire deletes a Voice’s trained copy at the upstream and refuses new speech in it, keeping the record and every File made. | [Privacy Officer](/agents/legal/privacy-officer) | [`Voice.retired`](/business/events/Voice.retired) | One-way (brand): `send`, `do` | | [Voice.get](/business/nouns/voice/get) | Returns one Voice by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Voice.list](/business/nouns/voice/list) | Returns Voices, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Voice.update](/business/nouns/voice/update) | Changes the given properties of a Voice. Inherited from [Noun](/business/nouns/noun). | None. | `Voice.updated` | Two-way: `try`, `send`, `do` | A Voice is never deleted: it ends by [Voice.retire](/business/nouns/voice/retire), and its records stay. ## Events Events no Verb emits. Each Verb’s Event is in the Verbs table above; every Event is delivered in the same shape. ### Voice.trained The upstream finished training a cloned or designed Voice, so speech renders in it. Raised by the rail. | Field | Type | Required | Description | | --- | --- | --- | --- | | `name` | `string` | Yes | `Voice.trained`. | | `at` | `datetime` | Yes | When it happened. | | `seq` | `integer` | No | Its position in the namespace, one more than the Event before; any seq is a cursor into the history. | | `data` | `json` | Yes | The Thing as the Action left it. | | `data.voice` | [Voice](/business/nouns/voice) | Yes | The Voice as the change left it. | | `data.voice.origin` | `string` | Yes | `cloned` from a real speaker’s recordings, or `designed` from a description and sounding like no real person. | | `data.voice.speaker` | [Person](/business/nouns/person) | No | The real person a cloned Voice sounds like. | | `data.voice.consent` | [Consent](/business/nouns/consent) | No | The speaker’s Consent, recorded in that voice, naming the Startup and the uses allowed; required for a cloned Voice. | | `data.voice.scope` | `string` | Yes | Who may speak in it: every sibling, one Startup, or one Customer. | | `data.voice.samples` | list of [File](/business/nouns/file) | No | The recordings it was trained from, kept forever. | | `data.voice.status` | `string` | Yes | `training` until the upstream finishes, `ready` for speech, `retired` once its trained copy is deleted. | | `data.previous.status` | `string` | Yes | The `status` before this Event: `training`. | ```json { "$id": "https://api.sb/kilnbakery.com/events/event_1", "$type": "Event", "name": "Voice.trained", "at": "2026-10-22T12:00:00Z", "data": { "voice": { "$id": "https://api.sb/kilnbakery.com/voices/voice_1", "$type": "Voice", "origin": "cloned", "speaker": "person_1", "consent": "consent_1", "scope": "studio", "samples": [ "file_1" ], "status": "ready" }, "previous": { "status": "training" } }, "seq": 1 } ``` ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Voice.get` | Yes | Yes | Yes | Yes | | `Voice.list` | Yes | Yes | Yes | Yes | | `Voice.update` | Yes | Yes | Yes | No | | `Voice.clone` | Yes | Yes | Yes | No | | `Voice.retire` | Yes | No | No | No | ## Call it **Ask** ```text Clone the latest voice with a person and a file and consent. ``` **API** ```bash curl -X POST https://api.sb/ledgerlark.com/voices/clone \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"speaker":"person_1","samples":["file_1"],"consent":"consent_1","scope":"studio"}' ``` ```json { "api": "https://api.sb/ledgerlark.com", "voice": { "$id": "https://api.sb/ledgerlark.com/voices/voice_1", "$type": "Voice", "origin": "cloned", "scope": "studio", "status": "training" }, "action": { "$id": "https://api.sb/ledgerlark.com/actions/action_1", "operation": "Voice.clone", "status": "done" }, "links": { "self": "https://api.sb/ledgerlark.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const voice = await $.Voice.clone({ speaker: 'person_1', samples: ['file_1'], consent: 'consent_1', scope: 'studio' }) ``` **CLI** ```bash npx startup-builder do Voice.clone --json '{"speaker":"person_1","samples":["file_1"],"consent":"consent_1","scope":"studio"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Voice.clone({ speaker: 'person_1', samples: ['file_1'], consent: 'consent_1', scope: 'studio' })" } } ``` ## Example A language-learning app designs a Voice from the description "warm, mid-pitch, unhurried". Its scope is the one [Startup](/business/nouns/startup), and every lesson's audio [File](/business/nouns/file) renders in it. # retire URL: /business/nouns/voice/retire · Id: `verb:Voice.retire` · Call: `await $.Voice.retire({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Retire deletes a Voice’s trained copy at the upstream and refuses new speech in it, keeping the record and every File made. Retire deletes a [Voice](/business/nouns/voice)’s trained copy at the upstream and refuses new speech in it, keeping the record and every [File](/business/nouns/file) made. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `voice` | [Voice](/business/nouns/voice) | Yes | The Voice to retire. | | `reason` | `text` | No | Why, such as Consent withdrawn. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `voice` | [Voice](/business/nouns/voice) | Yes | The Voice, now `retired`. | ## Effects - Emits [`Voice.retired`](/business/events/Voice.retired). - Performed by the [Privacy Officer](/agents/legal/privacy-officer). - One-way (brand): it waits out its delay window, and runs in the `send` and `do` modes. - Runs at once when the speaker withdraws Consent. - Deletes nothing in db.sb. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Voice.retire](/business/nouns/voice/retire) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Medium: one-way, bounded (brand) | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | 1 business hour, in which a watcher can pause, redirect or cancel it; then it runs. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Retire the latest voice. ``` **API** ```bash curl -X POST https://api.sb/shiftnote.app/voices/voice_1/retire \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/shiftnote.app", "voice": { "$id": "https://api.sb/shiftnote.app/voices/voice_1", "$type": "Voice", "origin": "cloned", "scope": "studio", "status": "training" }, "action": { "$id": "https://api.sb/shiftnote.app/actions/action_1", "operation": "Voice.retire", "status": "done" }, "links": { "self": "https://api.sb/shiftnote.app/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const voice = await $.Voice.retire({ voice: 'voice_1' }) ``` **CLI** ```bash npx startup-builder do Voice.retire --json '{"voice":"voice_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Voice.retire({ voice: 'voice_1' })" } } ``` # admit URL: /business/nouns/waitlist/admit · Id: `verb:Waitlist.admit` · Call: `await $.Waitlist.admit({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Admit releases Leads from a Waitlist to the Offer they waited for, in the order the Waitlist ranks them. Admit releases [Leads](/business/nouns/lead) from a [Waitlist](/business/nouns/waitlist) to the [Offer](/business/nouns/offer) they waited for, in the order the Waitlist ranks them. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `waitlist` | [Waitlist](/business/nouns/waitlist) | Yes | The Waitlist. | | `count` | `integer` | Yes | How many Leads to admit. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `leads` | list of [Lead](/business/nouns/lead) | Yes | The admitted Leads. | | `waitlist` | [Waitlist](/business/nouns/waitlist) | Yes | The Waitlist after the admitted Leads left it. | ## Effects - Emits [`Waitlist.admitted`](/business/events/Waitlist.admitted). - Performed by the [Sales Lead](/agents/sales/sales-lead). ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Waitlist.admit](/business/nouns/waitlist/admit) | | The record is not in a state that allows this Verb, so the call is refused. | [`refused`](/code/api/errors/refused) | Read the record, run the Verb that moves it to an allowed state, then retry. | [Waitlist.admit](/business/nouns/waitlist/admit) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Admit the latest waitlist. ``` **API** ```bash curl -X POST https://api.sb/tutorloop.com/waitlists/waitlist_1/admit \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"count":1}' ``` ```json { "api": "https://api.sb/tutorloop.com", "leads": [ { "$id": "https://api.sb/tutorloop.com/leads/lead_1", "$type": "Lead", "status": "new" } ], "waitlist": { "$id": "https://api.sb/tutorloop.com/waitlists/waitlist_1", "$type": "Waitlist", "invited": 1, "rank": "signup" }, "action": { "$id": "https://api.sb/tutorloop.com/actions/action_1", "operation": "Waitlist.admit", "status": "done" }, "links": { "self": "https://api.sb/tutorloop.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { leads, waitlist } = await $.Waitlist.admit({ waitlist: 'waitlist_1', count: 1 }) ``` **CLI** ```bash npx startup-builder do Waitlist.admit --json '{"waitlist":"waitlist_1","count":1}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Waitlist.admit({ waitlist: 'waitlist_1', count: 1 })" } } ``` Guides that call it: [Start a waitlist](/start/guides/start-a-waitlist). # Waitlist URL: /business/nouns/waitlist · Id: `noun:waitlist` > A Waitlist is the Leads waiting for an Offer that is not open to them, invited in the order a Setting chooses. A Waitlist is the [Leads](/business/nouns/lead) waiting for an [Offer](/business/nouns/offer) that is not open to them, invited in the order a [Setting](/business/nouns/setting) chooses. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `invited` | `integer` | No | How many Leads have been invited. | | `rank` | `string` | No | The invite order: first come, best ICP fit, or most referrals first. | ## Object ```json { "$id": "https://api.sb/patentpad.com/waitlists/waitlist_1", "$type": "Waitlist", "invited": 1, "rank": "signup" } ``` ## Relationships - A Waitlist **awaits** one [Offer](/business/nouns/offer): a Waitlist admits its [Leads](/business/nouns/lead) to one [Offer](/business/nouns/offer) once that Offer opens. `awaits`, inverse [`waitlist`](/business/nouns/offer#rel-waitlist). - A Waitlist **holds** many [Leads](/business/nouns/lead): [Leads](/business/nouns/lead) wait on a Waitlist in the order its [Setting](/business/nouns/setting) ranks them. `holds`, inverse [`waitsOn`](/business/nouns/lead#rel-waits-on). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Waitlist.admit](/business/nouns/waitlist/admit) | Admit releases Leads from a Waitlist to the Offer they waited for, in the order the Waitlist ranks them. | [Sales Lead](/agents/sales/sales-lead) | [`Waitlist.admitted`](/business/events/Waitlist.admitted) | None. | | [Waitlist.join](/business/nouns/waitlist/join) | Join adds a Lead to a Waitlist for an Offer that is not open to them. | [Marketing Lead](/agents/marketing/marketing-lead) | [`Waitlist.joined`](/business/events/Waitlist.joined) | None. | | [Waitlist.create](/business/nouns/waitlist/create) | Creates a Waitlist. Inherited from [Noun](/business/nouns/noun). | None. | `Waitlist.created` | Two-way: `try`, `send`, `do` | | [Waitlist.get](/business/nouns/waitlist/get) | Returns one Waitlist by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Waitlist.list](/business/nouns/waitlist/list) | Returns Waitlists, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Waitlist.update](/business/nouns/waitlist/update) | Changes the given properties of a Waitlist. Inherited from [Noun](/business/nouns/noun). | None. | `Waitlist.updated` | Two-way: `try`, `send`, `do` | | [Waitlist.delete](/business/nouns/waitlist/delete) | Deletes a Waitlist; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Waitlist.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Waitlist.create` | Yes | Yes | Yes | No | | `Waitlist.get` | Yes | Yes | Yes | Yes | | `Waitlist.list` | Yes | Yes | Yes | Yes | | `Waitlist.update` | Yes | Yes | Yes | No | | `Waitlist.delete` | Yes | Yes | Yes | No | | `Waitlist.admit` | Yes | Yes | Yes | No | | `Waitlist.join` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Join the latest waitlist. ``` **API** ```bash curl -X POST https://api.sb/shiftnote.app/waitlists/waitlist_1/join \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"email":"daniel@shiftnote.app"}' ``` ```json { "api": "https://api.sb/shiftnote.app", "lead": { "$id": "https://api.sb/shiftnote.app/leads/lead_1", "$type": "Lead", "status": "new" }, "waitlist": { "$id": "https://api.sb/shiftnote.app/waitlists/waitlist_1", "$type": "Waitlist", "invited": 1, "rank": "signup" }, "action": { "$id": "https://api.sb/shiftnote.app/actions/action_1", "operation": "Waitlist.join", "status": "done" }, "links": { "self": "https://api.sb/shiftnote.app/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { lead, waitlist } = await $.Waitlist.join({ waitlist: 'waitlist_1', email: 'daniel@shiftnote.app' }) ``` **CLI** ```bash npx startup-builder do Waitlist.join --json '{"waitlist":"waitlist_1","email":"daniel@shiftnote.app"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Waitlist.join({ waitlist: 'waitlist_1', email: 'daniel@shiftnote.app' })" } } ``` ## Example The team [Offer](/business/nouns/offer) of a lesson-booking [App](/business/nouns/app) has a Waitlist of 120 [Leads](/business/nouns/lead). A [Setting](/business/nouns/setting) admits 15 a week, in signup order. # join URL: /business/nouns/waitlist/join · Id: `verb:Waitlist.join` · Call: `await $.Waitlist.join({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Join adds a Lead to a Waitlist for an Offer that is not open to them. Join adds a [Lead](/business/nouns/lead) to a [Waitlist](/business/nouns/waitlist) for an [Offer](/business/nouns/offer) that is not open to them. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `waitlist` | [Waitlist](/business/nouns/waitlist) | Yes | The Waitlist to join. | | `email` | `email` | Yes | Where to reach the Lead. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `lead` | [Lead](/business/nouns/lead) | Yes | The waiting Lead. | | `waitlist` | [Waitlist](/business/nouns/waitlist) | Yes | The Waitlist joined. | ## Effects - Emits [`Waitlist.joined`](/business/events/Waitlist.joined). - Performed by the [Marketing Lead](/agents/marketing/marketing-lead). ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The input does not match the schema of the operation. | [`invalid-input`](/code/api/errors/invalid-input) | Read the schema of the operation, then send every required field with the right type. | [Waitlist.join](/business/nouns/waitlist/join) | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Waitlist.join](/business/nouns/waitlist/join) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Join the latest waitlist. ``` **API** ```bash curl -X POST https://api.sb/shiftnote.app/waitlists/waitlist_1/join \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"email":"daniel@shiftnote.app"}' ``` ```json { "api": "https://api.sb/shiftnote.app", "lead": { "$id": "https://api.sb/shiftnote.app/leads/lead_1", "$type": "Lead", "status": "new" }, "waitlist": { "$id": "https://api.sb/shiftnote.app/waitlists/waitlist_1", "$type": "Waitlist", "invited": 1, "rank": "signup" }, "action": { "$id": "https://api.sb/shiftnote.app/actions/action_1", "operation": "Waitlist.join", "status": "done" }, "links": { "self": "https://api.sb/shiftnote.app/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { lead, waitlist } = await $.Waitlist.join({ waitlist: 'waitlist_1', email: 'daniel@shiftnote.app' }) ``` **CLI** ```bash npx startup-builder do Waitlist.join --json '{"waitlist":"waitlist_1","email":"daniel@shiftnote.app"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Waitlist.join({ waitlist: 'waitlist_1', email: 'daniel@shiftnote.app' })" } } ``` # Watch URL: /business/nouns/watch · Id: `noun:watch` > A Watch is an outbound subscription that delivers the Events a selector matches to a URL, signed, retried, and replayable. A Watch is an outbound subscription that delivers the [Events](/business/nouns/event) a selector matches to a URL, signed, retried, and replayable. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `selector` | `string` | Yes | The Event selector, such as `Order.placed`. | | `url` | `url` | Yes | Where deliveries go. | | `payload` | `string` | No | One of `full`, or `thin`: the record as the Action left it, or only its versioned address. The default is full. | ## Object ```json { "$id": "https://api.sb/patentpad.com/watches/watch_1", "$type": "Watch", "selector": "Example selector", "url": "https://patentpad.com", "payload": "full" } ``` ## Relationships - A Watch **delivers** many [Events](/business/nouns/event): a Watch delivers each matching [Event](/business/nouns/event) to its URL, signed, retried and replayable. `delivers`, inverse [`deliveredBy`](/business/nouns/event#rel-delivered-by). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Watch.pause](/business/nouns/watch/pause) | Pause stops a Watch delivering while its Events keep queuing; the platform pauses a Watch whose deliveries fail for three days. | [Worker](/business/nouns/worker) | [`Watch.paused`](/business/events/Watch.paused) | None. | | [Watch.replay](/business/nouns/watch/replay) | Replay redelivers a Watch’s Events from a chosen point, signed as they were the first time. | [Quality Lead](/agents/quality/quality-lead) | [`Watch.replayed`](/business/events/Watch.replayed) | None. | | [Watch.resume](/business/nouns/watch/resume) | Resume restarts a paused Watch and delivers the Events it held, oldest first. | [Worker](/business/nouns/worker) | [`Watch.resumed`](/business/events/Watch.resumed) | None. | | [Watch.rotate](/business/nouns/watch/rotate) | Rotate issues a new signing secret for a Watch and signs with both secrets until the old one expires. | [Worker](/business/nouns/worker) | [`Watch.rotated`](/business/events/Watch.rotated) | None. | | [Watch.create](/business/nouns/watch/create) | Creates a Watch. Inherited from [Noun](/business/nouns/noun). | None. | `Watch.created` | Two-way: `try`, `send`, `do` | | [Watch.get](/business/nouns/watch/get) | Returns one Watch by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Watch.list](/business/nouns/watch/list) | Returns Watches, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Watch.update](/business/nouns/watch/update) | Changes the given properties of a Watch. Inherited from [Noun](/business/nouns/noun). | None. | `Watch.updated` | Two-way: `try`, `send`, `do` | | [Watch.delete](/business/nouns/watch/delete) | Deletes a Watch; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Watch.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Watch.create` | Yes | Yes | Yes | No | | `Watch.get` | Yes | Yes | Yes | Yes | | `Watch.list` | Yes | Yes | Yes | Yes | | `Watch.update` | Yes | Yes | Yes | No | | `Watch.delete` | Yes | Yes | Yes | No | | `Watch.pause` | Yes | Yes | Yes | No | | `Watch.replay` | Yes | Yes | Yes | No | | `Watch.resume` | Yes | Yes | Yes | No | | `Watch.rotate` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Replay the latest watch. ``` **API** ```bash curl -X POST https://api.sb/petpantry.shop/watches/watch_1/replay \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"from":"2026-10-22T12:00:00Z"}' ``` ```json { "api": "https://api.sb/petpantry.shop", "watch": { "$id": "https://api.sb/petpantry.shop/watches/watch_1", "$type": "Watch", "selector": "Example selector", "url": "https://petpantry.shop" }, "action": { "$id": "https://api.sb/petpantry.shop/actions/action_1", "operation": "Watch.replay", "status": "done" }, "links": { "self": "https://api.sb/petpantry.shop/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const watch = await $.Watch.replay({ watch: 'watch_1', from: '2026-10-22T12:00:00Z' }) ``` **CLI** ```bash npx startup-builder do Watch.replay --json '{"watch":"watch_1","from":"2026-10-22T12:00:00Z"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Watch.replay({ watch: 'watch_1', from: '2026-10-22T12:00:00Z' })" } } ``` ## Example A dental group registers a Watch for `Reminder.confirmed` [Events](/business/nouns/event) to `https://hooks.brightsmiles.dental/reminders`. Each delivery is signed, retried on failure, and replayable after an outage. # pause URL: /business/nouns/watch/pause · Id: `verb:Watch.pause` · Call: `await $.Watch.pause({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Pause stops a Watch delivering while its Events keep queuing; the platform pauses a Watch whose deliveries fail for three days. Pause stops a [Watch](/business/nouns/watch) delivering while its [Events](/business/nouns/event) keep queuing; the platform pauses a Watch whose deliveries fail for three days. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `watch` | [Watch](/business/nouns/watch) | Yes | The Watch to pause. | | `reason` | `text` | No | Why deliveries stop. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `watch` | [Watch](/business/nouns/watch) | Yes | The paused Watch. | ## Effects - Emits [`Watch.paused`](/business/events/Watch.paused). - Holds every matching Event in order until the Watch resumes. - Notifies the Reliability Engineer when the platform pauses it. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Watch.pause](/business/nouns/watch/pause) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Pause the latest watch. ``` **API** ```bash curl -X POST https://api.sb/routewise.dev/watches/watch_1/pause \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/routewise.dev", "watch": { "$id": "https://api.sb/routewise.dev/watches/watch_1", "$type": "Watch", "selector": "Example selector", "url": "https://routewise.dev" }, "action": { "$id": "https://api.sb/routewise.dev/actions/action_1", "operation": "Watch.pause", "status": "done" }, "links": { "self": "https://api.sb/routewise.dev/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const watch = await $.Watch.pause({ watch: 'watch_1' }) ``` **CLI** ```bash npx startup-builder do Watch.pause --json '{"watch":"watch_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Watch.pause({ watch: 'watch_1' })" } } ``` # replay URL: /business/nouns/watch/replay · Id: `verb:Watch.replay` · Call: `await $.Watch.replay({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Replay redelivers a Watch’s Events from a chosen point, signed as they were the first time. Replay redelivers a [Watch](/business/nouns/watch)’s [Events](/business/nouns/event) from a chosen point, signed as they were the first time. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `watch` | [Watch](/business/nouns/watch) | Yes | The Watch to replay. | | `from` | `datetime` | Yes | Where the replay starts. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `watch` | [Watch](/business/nouns/watch) | Yes | The Watch, replaying. | ## Effects - Emits [`Watch.replayed`](/business/events/Watch.replayed). - Performed by the [Quality Lead](/agents/quality/quality-lead). ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The input does not match the schema of the operation. | [`invalid-input`](/code/api/errors/invalid-input) | Read the schema of the operation, then send every required field with the right type. | [Watch.replay](/business/nouns/watch/replay) | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Watch.replay](/business/nouns/watch/replay) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Replay the latest watch. ``` **API** ```bash curl -X POST https://api.sb/petpantry.shop/watches/watch_1/replay \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"from":"2026-10-22T12:00:00Z"}' ``` ```json { "api": "https://api.sb/petpantry.shop", "watch": { "$id": "https://api.sb/petpantry.shop/watches/watch_1", "$type": "Watch", "selector": "Example selector", "url": "https://petpantry.shop" }, "action": { "$id": "https://api.sb/petpantry.shop/actions/action_1", "operation": "Watch.replay", "status": "done" }, "links": { "self": "https://api.sb/petpantry.shop/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const watch = await $.Watch.replay({ watch: 'watch_1', from: '2026-10-22T12:00:00Z' }) ``` **CLI** ```bash npx startup-builder do Watch.replay --json '{"watch":"watch_1","from":"2026-10-22T12:00:00Z"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Watch.replay({ watch: 'watch_1', from: '2026-10-22T12:00:00Z' })" } } ``` # resume URL: /business/nouns/watch/resume · Id: `verb:Watch.resume` · Call: `await $.Watch.resume({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Resume restarts a paused Watch and delivers the Events it held, oldest first. Resume restarts a paused [Watch](/business/nouns/watch) and delivers the [Events](/business/nouns/event) it held, oldest first. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `watch` | [Watch](/business/nouns/watch) | Yes | The paused Watch. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `watch` | [Watch](/business/nouns/watch) | Yes | The Watch, delivering again. | ## Effects - Emits [`Watch.resumed`](/business/events/Watch.resumed). - Delivers the held Events in sequence order. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Watch.resume](/business/nouns/watch/resume) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Resume the latest watch. ``` **API** ```bash curl -X POST https://api.sb/petpantry.shop/watches/watch_1/resume \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/petpantry.shop", "watch": { "$id": "https://api.sb/petpantry.shop/watches/watch_1", "$type": "Watch", "selector": "Example selector", "url": "https://petpantry.shop" }, "action": { "$id": "https://api.sb/petpantry.shop/actions/action_1", "operation": "Watch.resume", "status": "done" }, "links": { "self": "https://api.sb/petpantry.shop/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const watch = await $.Watch.resume({ watch: 'watch_1' }) ``` **CLI** ```bash npx startup-builder do Watch.resume --json '{"watch":"watch_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Watch.resume({ watch: 'watch_1' })" } } ``` # rotate URL: /business/nouns/watch/rotate · Id: `verb:Watch.rotate` · Call: `await $.Watch.rotate({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves. > Rotate issues a new signing secret for a Watch and signs with both secrets until the old one expires. Rotate issues a new signing secret for a [Watch](/business/nouns/watch) and signs with both secrets until the old one expires. ## Inputs | Input | Type | Required | Description | | --- | --- | --- | --- | | `watch` | [Watch](/business/nouns/watch) | Yes | The Watch whose secret changes. | | `overlap` | `string` | No | How long the old secret keeps signing, as an ISO 8601 duration; defaults to `PT24H`. | ## Outputs | Output | Type | Required | Description | | --- | --- | --- | --- | | `watch` | [Watch](/business/nouns/watch) | Yes | The Watch, signing with both secrets. | | `secret` | `string` | Yes | The new signing secret, shown once. | ## Effects - Emits [`Watch.rotated`](/business/events/Watch.rotated). - Adds a second signature to every delivery until the overlap ends. - Retires the old secret when the overlap ends. ## Refuses when | Check | Error | Fix | Then call | | --- | --- | --- | --- | | The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | [Watch.rotate](/business/nouns/watch/rotate) | ## When it waits | Gate | Default | | --- | --- | | Decision class | Low: two-way, nothing at stake | | [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. | | Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. | | Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval) from the [Founder](/agents/founding/founder). Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. | ## Example **Ask** ```text Rotate the latest watch. ``` **API** ```bash curl -X POST https://api.sb/kilnbakery.com/watches/watch_1/rotate \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ```json { "api": "https://api.sb/kilnbakery.com", "watch": { "$id": "https://api.sb/kilnbakery.com/watches/watch_1", "$type": "Watch", "selector": "Example selector", "url": "https://kilnbakery.com" }, "secret": "Example secret", "action": { "$id": "https://api.sb/kilnbakery.com/actions/action_1", "operation": "Watch.rotate", "status": "done" }, "links": { "self": "https://api.sb/kilnbakery.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { watch, secret } = await $.Watch.rotate({ watch: 'watch_1' }) ``` **CLI** ```bash npx startup-builder do Watch.rotate --json '{"watch":"watch_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Watch.rotate({ watch: 'watch_1' })" } } ``` # Worker URL: /business/nouns/worker · Id: `noun:worker` > A Worker is a Human or an Agent that fills a Role and acts on Tasks. A Worker is a [Human](/business/nouns/human) or an [Agent](/business/nouns/agent) that fills a [Role](/business/nouns/role) and acts on [Tasks](/business/nouns/task). ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `name` | `string` | Yes | The name the Worker goes by in a Startup. | | `instructions` | `text` | No | How the Worker does its work. | ## Object ```json { "$id": "https://api.sb/quietcopy.com/workers/worker_1", "$type": "Worker", "name": "QuietCopy", "instructions": "Example instructions" } ``` ## Relationships - A Worker **carries** many [Cards](/business/nouns/card): a Worker carries the [Cards](/business/nouns/card) issued for its [Mandates](/business/nouns/mandate); the cardholder on the rail is always the [Company](/business/nouns/company). `carries`, inverse [`carriedBy`](/business/nouns/card#rel-carried-by). - A Worker **has** many [Conversations](/business/nouns/conversation): one Worker owes each [Conversation](/business/nouns/conversation) its next answer. `conversations`, inverse [`awaits`](/business/nouns/conversation#rel-awaits). - A Worker **fills** many [Roles](/business/nouns/role): a Worker, human or agent, fills a [Role](/business/nouns/role) and acts under its [Permissions](/business/nouns/permission); one [Agent](/business/nouns/agent) can fill Roles in many [Startups](/business/nouns/startup). `fills`, inverse [`filledBy`](/business/nouns/role#rel-filled-by). - A Worker **has access** many [Access Levels](/business/nouns/access-level): a Worker holds one [Access Level](/business/nouns/access-level) in each namespace it works in, apart from the [Role](/business/nouns/role) it fills. `hasAccess`, inverse [`workers`](/business/nouns/access-level#rel-workers). - A Worker **holds** many [Credentials](/business/nouns/credential): a Worker performs a [Reserved Act](/business/nouns/reserved-act) only while it holds the [Credential](/business/nouns/credential) that authorizes it, in good standing. `holds`, inverse [`heldBy`](/business/nouns/credential#rel-held-by). - A Worker **has** one [Mailbox](/business/nouns/mailbox): every Worker, [Agent](/business/nouns/agent) or [Human](/business/nouns/human), has its own [Mailbox](/business/nouns/mailbox). `mailbox`, inverse [`belongsTo`](/business/nouns/mailbox#rel-belongs-to). - A Worker **practices** many [Skills](/business/nouns/skill): the [Skills](/business/nouns/skill) a Worker has, each at a level, matched against what [Roles](/business/nouns/role) require. `practices`, inverse [`practicedBy`](/business/nouns/skill#rel-practiced-by). - A Worker **remembers** one [Memory](/business/nouns/memory): a Worker’s own [Memory](/business/nouns/memory) of what it has learned, read by its [Functions](/business/nouns/function) and kept within its [Startup](/business/nouns/startup). `remembers`, inverse [`heldBy`](/business/nouns/memory#rel-held-by). - A Worker **staffs** many [Services](/business/nouns/service): a [Service](/business/nouns/service)’s outcome is delivered by the [Agents](/business/nouns/agent) and [Humans](/business/nouns/human) who fill its [Roles](/business/nouns/role). `staffs`, inverse [`requires`](/business/nouns/service#rel-requires). - A Worker **has** many [Tasks](/business/nouns/task): the Worker a [Task](/business/nouns/task) waits on; the Task sits in that Worker’s inbox until it is done. `tasks`, inverse [`assignedTo`](/business/nouns/task#rel-assigned-to). - A Worker **uses** many [Tools](/business/nouns/tool): the [Tools](/business/nouns/tool) a Worker may call, narrowed to its [Role](/business/nouns/role)’s [Permissions](/business/nouns/permission). `uses`, inverse [`usedBy`](/business/nouns/tool#rel-used-by). - A Worker **writes** many [Comments](/business/nouns/comment): every [Comment](/business/nouns/comment) names the Worker, human or agent, who wrote it. `writes`, inverse [`author`](/business/nouns/comment#rel-author). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Action.ask](/business/nouns/action/ask) | Ask puts a Question to a Party, a Role, or a Worker and holds the Action `pending` with reason `awaitingInput`. | [Worker](/business/nouns/worker) | [`Action.asked`](/business/events/Action.asked) | Two-way: `try`, `send`, `do` | | [Portfolio.brake](/business/nouns/portfolio/brake) | Brake stops one class of effects, such as sends, spend, publishes, or price changes, across a Portfolio query until it expires or is lifted. | [Worker](/business/nouns/worker) | [`Portfolio.braked`](/business/events/Portfolio.braked) | None. | | [Task.claim](/business/nouns/task/claim) | Claim takes an offered Task from a shared queue or a handoff and makes the calling Worker its assignee. | [Supply Manager](/agents/operations/supply-manager) | [`Task.claimed`](/business/events/Task.claimed) | None. | | [Task.complete](/business/nouns/task/complete) | Complete marks a Task done and resumes the Action that waited on it. | [Supply Manager](/agents/operations/supply-manager) | [`Task.completed`](/business/events/Task.completed) | None. | | [Dispute.decide](/business/nouns/dispute/decide) | Decide rules on an answered Dispute for the buyer, the seller, or a split, and releases or returns the held amount. | [Billing Specialist](/agents/finance/billing-specialist) | [`Dispute.decided`](/business/events/Dispute.decided) | One-way (money, customer): `send`, `do` | | [Portfolio.lift](/business/nouns/portfolio/lift) | Lift ends a brake before it expires, and the Actions it held resume their review and delay windows. | [Worker](/business/nouns/worker) | [`Portfolio.lifted`](/business/events/Portfolio.lifted) | None. | | [Task.next](/business/nouns/task/next) | Next returns the oldest open Task the calling Worker’s Roles may claim, without claiming it. | [Worker](/business/nouns/worker) | [`Task.offered`](/business/events/Task.offered) | None. | | [Action.pause](/business/nouns/action/pause) | Pause holds a pending Action past the close of its delay window until a watcher resumes, redirects, or cancels it. | [Worker](/business/nouns/worker) | [`Action.paused`](/business/events/Action.paused) | None. | | [Watch.pause](/business/nouns/watch/pause) | Pause stops a Watch delivering while its Events keep queuing; the platform pauses a Watch whose deliveries fail for three days. | [Worker](/business/nouns/worker) | [`Watch.paused`](/business/events/Watch.paused) | None. | | [Integration.pause](/business/nouns/integration/pause) | Pause stops every call through an Integration at once and keeps its token and cursor. | [Worker](/business/nouns/worker) | [`Integration.paused`](/business/events/Integration.paused) | Two-way: `try`, `send`, `do` | | [Integration.reconnect](/business/nouns/integration/reconnect) | Reconnect re-approves an Integration in place, keeping its id and cursor, so nothing re-imports. | [Worker](/business/nouns/worker) | [`Integration.reconnected`](/business/events/Integration.reconnected) | Two-way: `try`, `send`, `do` | | [Action.resume](/business/nouns/action/resume) | Resume ends a pause and lets the Action run as reviewed, or reopen what remained of its delay window. | [Worker](/business/nouns/worker) | [`Action.resumed`](/business/events/Action.resumed) | None. | | [Watch.resume](/business/nouns/watch/resume) | Resume restarts a paused Watch and delivers the Events it held, oldest first. | [Worker](/business/nouns/worker) | [`Watch.resumed`](/business/events/Watch.resumed) | None. | | [Integration.resume](/business/nouns/integration/resume) | Resume restarts a paused Integration from its cursor and releases the Actions that waited on it. | [Worker](/business/nouns/worker) | [`Integration.resumed`](/business/events/Integration.resumed) | Two-way: `try`, `send`, `do` | | [Task.return](/business/nouns/task/return) | Return hands an offered Task back to its sender, unchanged, with the reason the receiver cannot take it. | [Supply Manager](/agents/operations/supply-manager) | [`Task.returned`](/business/events/Task.returned) | None. | | [Integration.revoke](/business/nouns/integration/revoke) | Revoke ends an Integration at once: its token is revoked with the upstream, and every record it brought in stays. | [Security Engineer](/agents/engineering/security-engineer) | [`Integration.revoked`](/business/events/Integration.revoked) | None. | | [Watch.rotate](/business/nouns/watch/rotate) | Rotate issues a new signing secret for a Watch and signs with both secrets until the old one expires. | [Worker](/business/nouns/worker) | [`Watch.rotated`](/business/events/Watch.rotated) | None. | | [Noun.trace](/business/nouns/noun/trace) | Trace lists every Verb, Process, Offer, Dashboard and Version that references a Noun, so an edit or a retire shows its reach first. | [Worker](/business/nouns/worker) | [`Noun.traced`](/business/events/Noun.traced) | None. | | [Worker.create](/business/nouns/worker/create) | Creates a Worker. Inherited from [Noun](/business/nouns/noun). | None. | `Worker.created` | Two-way: `try`, `send`, `do` | | [Worker.get](/business/nouns/worker/get) | Returns one Worker by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Worker.list](/business/nouns/worker/list) | Returns Workers, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Worker.update](/business/nouns/worker/update) | Changes the given properties of a Worker. Inherited from [Noun](/business/nouns/noun). | None. | `Worker.updated` | Two-way: `try`, `send`, `do` | | [Worker.delete](/business/nouns/worker/delete) | Deletes a Worker; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Worker.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Worker.create` | Yes | Yes | Yes | No | | `Worker.get` | Yes | Yes | Yes | Yes | | `Worker.list` | Yes | Yes | Yes | Yes | | `Worker.update` | Yes | Yes | Yes | No | | `Worker.delete` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Add a worker to TutorLoop. ``` **API** ```bash curl -X POST https://api.sb/tutorloop.com/workers \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"name":"TutorLoop"}' ``` ```json { "api": "https://api.sb/tutorloop.com", "worker": { "$id": "https://api.sb/tutorloop.com/workers/worker_1", "$type": "Worker", "name": "TutorLoop" }, "action": { "$id": "https://api.sb/tutorloop.com/actions/action_1", "operation": "Worker.create", "status": "done" }, "links": { "self": "https://api.sb/tutorloop.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const worker = await $.Worker.create({ name: 'TutorLoop' }) ``` **CLI** ```bash npx startup-builder do Worker.create --json '{"name":"TutorLoop"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Worker.create({ name: 'TutorLoop' })" } } ``` ## Example At a tax-preparation service, Nora the [Payroll Specialist](/agents/people/payroll-specialist) and a credentialed preparer are both Workers. Each fills a [Role](/business/nouns/role), works [Tasks](/business/nouns/task), and keeps its own [Memory](/business/nouns/memory). # Workflow URL: /business/nouns/workflow · Id: `noun:workflow` > A Workflow is the durable, executable body of one Action: its steps, the Functions that run them, retries, and waits. A Workflow is the durable, executable body of one [Action](/business/nouns/action): its steps, the [Functions](/business/nouns/function) that run them, retries, and waits. [Triggers](/business/nouns/trigger) start it, and a [Process](/business/nouns/process) groups it with others. ## Properties | Property | Type | Required | Description | | --- | --- | --- | --- | | `steps` | `json` | Yes | The ordered steps, each run by a Function. | | `retries` | `integer` | No | How many times a failed step retries. | | `body` | `string` | No | The Verb whose Action it is the durable body of, such as `Order.refund`; a Workflow with a body has no Trigger. | ## Object ```json { "$id": "https://api.sb/patentpad.com/workflows/workflow_1", "$type": "Workflow", "steps": {}, "retries": 1, "body": "Example body" } ``` ## Relationships - A Workflow **executes** one [Action](/business/nouns/action): a Workflow is the durable body of one [Action](/business/nouns/action): its steps, retries and waits. `executes`, inverse [`executedBy`](/business/nouns/action#rel-executed-by). - A Workflow **is started by** many [Triggers](/business/nouns/trigger): when a [Trigger](/business/nouns/trigger) fires, each Workflow it starts runs as a new [Action](/business/nouns/action). `startedBy`, inverse [`starts`](/business/nouns/trigger#rel-starts). - A Workflow **is used in** one [Process](/business/nouns/process): a [Process](/business/nouns/process) does its work through Workflows, each the durable, executable part of the Process. `usedIn`, inverse [`uses`](/business/nouns/process#rel-uses). ## Verbs | Verb | Description | Subject | Event | Class | | --- | --- | --- | --- | --- | | [Workflow.create](/business/nouns/workflow/create) | Creates a Workflow. Inherited from [Noun](/business/nouns/noun). | None. | `Workflow.created` | Two-way: `try`, `send`, `do` | | [Workflow.get](/business/nouns/workflow/get) | Returns one Workflow by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Workflow.list](/business/nouns/workflow/list) | Returns Workflows, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` | | [Workflow.update](/business/nouns/workflow/update) | Changes the given properties of a Workflow. Inherited from [Noun](/business/nouns/noun). | None. | `Workflow.updated` | Two-way: `try`, `send`, `do` | | [Workflow.delete](/business/nouns/workflow/delete) | Deletes a Workflow; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Workflow.deleted` | One-way: `send`, `do` | ## Permissions Which Access level may call each Verb. One-way Verbs wait their delay window. | Operation | `owner` | `admin` | `member` | `viewer` | | --- | --- | --- | --- | --- | | `Workflow.create` | Yes | Yes | Yes | No | | `Workflow.get` | Yes | Yes | Yes | Yes | | `Workflow.list` | Yes | Yes | Yes | Yes | | `Workflow.update` | Yes | Yes | Yes | No | | `Workflow.delete` | Yes | Yes | Yes | No | ## Call it **Ask** ```text Add a workflow to ShiftNote. ``` **API** ```bash curl -X POST https://api.sb/shiftnote.app/workflows \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"steps":{}}' ``` ```json { "api": "https://api.sb/shiftnote.app", "workflow": { "$id": "https://api.sb/shiftnote.app/workflows/workflow_1", "$type": "Workflow", "steps": {} }, "action": { "$id": "https://api.sb/shiftnote.app/actions/action_1", "operation": "Workflow.create", "status": "done" }, "links": { "self": "https://api.sb/shiftnote.app/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const workflow = await $.Workflow.create({ steps: {} }) ``` **CLI** ```bash npx startup-builder do Workflow.create --json '{"steps":{}}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Workflow.create({ steps: {} })" } } ``` ## Example At a translation marketplace, the Workflow behind `Order.fulfill` drafts the translation, then waits up to 48 hours for the translator’s certification. With `retries: 3`, a failed upload runs three more times before the Workflow stops. # What gets set up, in order URL: /business/provisioning · Id: `page:business/provisioning` > The order in which a new Startup comes up, how long each outside party takes, and the Event that tells your agent each step is done. Everything a [Startup](/business/nouns/startup) needs that nobody outside the platform decides is ready in its first minute. Six steps wait on someone else, and each ends with an [Event](/business/nouns/event) your agent can wait for. ## The first minute `Startup.create` records the business and answers at a claimed name at once. Its `Startup.created` Event starts three [Workflows](/business/nouns/workflow), and [`Startup.build`](/business/nouns/startup/build) provisions the rest of the definition. | What you get | Set up by | Done when | | --- | --- | --- | | An agent in every [Role](/business/nouns/role), with its [Permissions](/business/nouns/permission) and [Limits](/business/nouns/limit) | [Staff roles](/workflows/processes/staffing/staff-roles) | [`Role.staffed`](/business/events/Role.staffed), once per Role | | An [Integration](/business/nouns/integration) with each capability's default provider, each tested | [Connect providers](/systems/integrations/provider-wiring/connect-providers) | [`Integration.connected`](/business/events/Integration.connected), once per provider | | Terms and a privacy notice, published on the [Site](/business/nouns/site) | [Publish terms](/workflows/processes/contracting/publish-terms) | The Workflow's [Action](/business/nouns/action) finishes | | [Systems](/business/nouns/system), the Site, the [App](/business/nouns/app), and the API, SDK, CLI and MCP server | [`Startup.build`](/business/nouns/startup/build) | [`Startup.built`](/business/events/Startup.built) | `Startup.build` runs once the Building checks pass, and it names each check that fails. The [launch checklist](/start/launch-checklist) lists them. ## What waits on someone else | Step | Waits on | How long | Done when | | --- | --- | --- | --- | | Claim the Startup with [`Startup.claim`](/business/nouns/startup/claim) | You, and Stripe's check of who you are | Minutes for most owners | [`Startup.claimed`](/business/events/Startup.claimed) | | Your own [Domain](/business/nouns/domain), by [`Domain.register`](/business/nouns/domain/register) or [`Domain.connect`](/business/nouns/domain/connect) | The registrar, then public DNS | Minutes when registered here; up to 48 hours when it moves from another registrar | [`Domain.verified`](/business/events/Domain.verified), with the Domain `live` | | The first payout to your bank | Stripe's payout schedule | 7 to 14 days after the first payment | `Transaction.settled` on the payout | | A [Mailbox](/business/nouns/mailbox) at full volume | Mail providers learning to trust a new address | Two to four weeks of rising daily sends | [`Mailbox.warmed`](/business/events/Mailbox.warmed) | | A [Company](/business/nouns/company) of its own, through [Form a company](/workflows/processes/incorporation/form-company) | The state, the tax authority, then the bank | The certificate files the same day; the tax id, bank account and founder [Shares](/business/nouns/share) follow in that order | [`Company.incorporated`](/business/events/Company.incorporated), then [`Share.issued`](/business/events/Share.issued) | | Going live with [`Startup.launch`](/business/nouns/startup/launch) | The Live checks, and your approval | As long as the checks take to pass | [`Startup.launched`](/business/events/Startup.launched) | ## Work while you wait Nothing waits on a slow step except what needs it. Before the claim, no [Verb](/business/nouns/verb) moves real money; the Site serves, [Leads](/business/nouns/lead) join the [Waitlist](/business/nouns/waitlist), and every agent works. A warming Mailbox sends up to its daily cap, so outbound starts on the first day at low volume. A new Domain serves the moment it verifies, and the claimed name keeps answering beside it. ## Wait for it in code Each row ends in an Event, so an agent waits for the Event instead of polling. To follow every step of one Startup, run: ```bash npx startup-builder listen 'Startup.*' npx startup-builder listen Domain.verified ``` A [Trigger](/business/nouns/trigger) on the same Event starts your own [Workflow](/business/nouns/workflow) when a step finishes, such as a launch announcement on `Startup.launched`. # Customers and hypothesis URL: /business/record/customers-and-hypothesis · Id: `page:business/record/customers-and-hypothesis` > The ICP a Startup serves, the Problem it solves, and the founding Hypothesis whose five slots Evidence grades one week at a time. A [Startup](/business/nouns/startup) serves one [ICP](/business/nouns/icp) and the [Problem](/business/nouns/problem) that ICP already pays to solve. Its founding [Hypothesis](/business/nouns/hypothesis) says why that ICP switches, in five slots that outside [Evidence](/business/nouns/evidence) grades. ## The ICP and its Personas An ICP names who the Startup is built to win. For platecost.app, it is an independent restaurant with one to three locations whose food cost runs above 30% of sales. Inside one ICP sit several [Personas](/business/nouns/persona), each with its own job. The owner accepts the [Offer](/business/nouns/offer), the chef updates recipes, and the bookkeeper's [Agent](/business/nouns/agent) pulls the weekly cost export. The one who pays, the one who uses, and the one who benefits are often different, and one of them is software. Before a party accepts an Offer, at any [Price](/business/nouns/price) including zero, it is a [Prospect](/business/nouns/prospect). After, it is a [Customer](/business/nouns/customer). A Startup keeps one ICP until it reaches [Repeatable](/business/lifecycle/states/repeatable); a second ICP gets a sibling Startup pursuing the same [Idea](/business/nouns/idea). ## The Problem in their words A Problem records what the ICP struggles with, how they solve it today, and what that costs. The words are theirs, not the Startup's. > Every time the produce prices move, the food-cost sheet gets rebuilt by hand. That is my whole weekend. Those words name the work, its frequency, and its cost. Four hours a week of an owner's time, or the $400 a month a bookkeeper charges for the same sheet, anchors what platecost.app can charge. The Problem also records three facts about the work: - The moment that starts it: a new supplier invoice. - The progress wanted: from guessing margins to knowing them per plate. - What the ICP uses today: a spreadsheet, a bookkeeper, or nothing. A Problem with no current cost has no market. ## The founding Hypothesis The founding Hypothesis is the root of the definition: one sentence in a fixed shape. platecost.app writes this one: ```text If we help independent restaurants with one to three locations solve food-cost drift from changing supplier prices with plate costs recomputed from every invoice they photograph, they will choose it over the spreadsheet and the bookkeeper because margins update the same day, per plate, for $79 a month. ``` Each of its five slots is a child Hypothesis with its own [Metric](/business/nouns/metric) and threshold. The sentence stays a draft until every slot names both. | Slot | Claim | Settled when | | --- | --- | --- | | Customer | These restaurants exist and answer | 15 of 40 owners contacted take an [Interview](/business/nouns/interview) | | Problem | They rebuild cost sheets by hand, weekly | 10 of 15 Interviews describe the rebuild unprompted | | Approach | Photographed invoices give correct plate costs | 95% of invoice lines parse without correction | | Switch | They pay to stop | 8 refundable $79 deposits within 14 days | | Differentiation | Same-day margins beat a lower price | "Margins every morning" outsells "cheaper than a bookkeeper" on deposits | Beside the sentence, the [Founder](/agents/founding/founder) sets one number: the minimum success criteria, a [Goal](/business/nouns/goal) of outside revenue by a date. platecost.app sets $4,000 a month within nine months. [Strategy, Goals, and economics](/business/record/strategy-goals-and-economics) turns that number into dated targets. ## Grading Evidence Evidence is a recorded quote, reading, or artifact bound to the slot it supports or refutes. Each slot shows the strongest grade among its outside Evidence. | Grade | platecost.app example | Weight | | --- | --- | --- | | Behavior | A paid month, then a second one | Highest: observed, not promised | | Commitment | A refundable deposit or a booked onboarding call | Real: it costs the giver something | | Opinion | "I would pay for that." | Zero: free to give | | None | Nothing recorded | Zero | Opinions stay on the record and weigh nothing. Only outside parties grade a slot, so a sibling Startup, the [Studio](/business/nouns/studio), or a friend of the Founder never moves one. [Lifecycle](/business/nouns/lifecycle) gates read grades, never filled-in fields. platecost.app cannot leave [Idea](/business/lifecycle/states/idea) by typing into the switch slot; it leaves when deposits land. ## The weekly test At the start of each week the Startup ranks its five slots by (1 − grade) × impact. Impact is how far a wrong slot would move the minimum success criteria. The weakest slot gets the week's one [Experiment](/business/nouns/experiment), and that Experiment's Metric is the one metric that matters. At the end of the week, office hours reads the Evidence and writes one [Decision](/business/nouns/decision): keep the slot, revise it, or test again. The first test is usually reserve-first. platecost.app publishes a reserve page the same day, taking refundable deposits on the $79 Offer, and sends 40 owners there. Talk is cheaper but settles less: once ten more Interviews would leave the Decision unchanged, the Startup stops interviewing. ## One Product, several stories The same [Product](/business/nouns/product) needs a different story for each Persona. The owner hears the margin and the price; the chef hears "no more weekend spreadsheets" and sees the recipe screen. An Agent buying for a restaurant group needs none of that prose. It needs the schema, the terms, the turnaround, and the Price, all machine-readable. Every one of those stories compiles from the founding Hypothesis and the Interview quotes, and each sentence records the slot it came from. Revise the differentiation slot and every headline built on it recompiles, with the [Change](/business/nouns/change) previewed before it lands. ## Next [Products, Offers and revenue](/products/offers-and-revenue): what the Startup sells, and how a sale becomes revenue. # Identity and structure URL: /business/record/identity-and-structure · Id: `page:business/record/identity-and-structure` > What counts as one Startup, how it differs from its Idea, Brand, Company, Studio, and Portfolio, and the two trees it sits in. A [Startup](/business/nouns/startup) is the smallest business that can be moved, promoted, or sold on its own, together with its [Customers](/business/nouns/customer). Everything else that names it answers a different question and keeps its own record. ## The boundary test Ask one question: could this be sold with its Customers, as a unit, without tearing anything? If yes, it is one Startup. If two parts would have to be split first, they are two. permitpulse.dev sells general contractors two things. One is a [Dataset](/business/nouns/dataset) of every building permit filed in their county. The other is an [Agent](/business/nouns/agent) that prepares and files the contractor's own permit applications. Both [Products](/business/nouns/product) serve the same contractors and share one P&L, so permitpulse.dev is one Startup. Now suppose the same team sells permit histories to property insurers under the same name. Different Customers, different economics, a separate sale: that is a second Startup sharing a [Brand](/business/nouns/brand). The reverse holds too. permitpulse.dev, api.permitpulse.dev, and a regional alias are three [Domains](/business/nouns/domain) for one Startup. Count Startups by the boundary test, never by Domains, Brands, or repositories. ## Six records, six questions Six records surround a Startup. Each answers one question, and none stands in for another. | Record | [Question](/business/nouns/question) it answers | For permitpulse.dev | | --- | --- | --- | | [Idea](/business/nouns/idea) | What is pursued? | Permits that file themselves | | Startup | Which business serves and earns? | permitpulse.dev | | Brand | How are its [Offers](/business/nouns/offer) presented? | Its name, voice, logo, and colors | | [Studio](/business/nouns/studio) | Who builds and directs it? | The Studio that minted it | | [Company](/business/nouns/company) | Who holds its rights and signs? | The Studio's holding Company | | [Portfolio](/business/nouns/portfolio) | Where do attention and money go? | The Studio's construction Portfolio | Each edit touches one record. A rebrand changes the Brand, and no second Startup appears. A move to a new Company changes the legal holder, and a new Domain adds an address, so history stays legible. ## Two trees A Startup sits in two trees at once, and they answer different questions. The operating tree runs Studio, Portfolio, Startup, Product. Direction flows down it, and so do [Settings](/business/nouns/setting): each record inherits a Setting from its nearest holder unless it sets its own. The Studio sets a 14-day refund window; permitpulse.dev inherits it, and its filing Agent overrides it with 7 days. The legal tree runs from Company to Startup. The Company signs [Agreements](/business/nouns/agreement), owns the equity, and holds the profit rights. The trees move independently. When permitpulse.dev moves to a Company of its own, its operating parent, Settings, Domains, and Customers stay where they were. A Company officer who signs a lease gains no operating [Permission](/business/nouns/permission), and the Agent that files permits owns nothing. ## An Idea outlives its Startups An Idea exists apart from any Startup that pursues it. The Studio often mints three to five sibling Startups for one Idea, each a variant with its own [ICP](/business/nouns/icp), approach, and Brand. The siblings run as one [Experiment](/business/nouns/experiment), judged on deposits from outside Customers. "Permits that file themselves" spawned two siblings: permitpulse.dev for general contractors and a second Startup for rooftop solar installers. Installers filed more often but paid less per filing, so the Studio kept funding both and let the numbers decide. A variant that loses goes [Dormant](/business/lifecycle/states/dormant). Nothing is deleted, and the Idea keeps every piece of [Evidence](/business/nouns/evidence) for the next attempt. ## Built from templates Every Startup extends a [Startup Template](/business/nouns/startup-template). A Startup Template combines an operating model, one or more [Product Templates](/business/nouns/product-template), and a [Motion](/business/nouns/motion) for each Offer. permitpulse.dev runs the [Autonomous](/agents/operating-models/autonomous) operating model, with no [Humans](/business/nouns/human) in its [Roles](/business/nouns/role). Its Products extend the [Dataset API](/products/templates/dataset-api) and [Agent as a Service](/products/templates/agent-as-a-service) Product Templates. Both Offers sell [b2b](/business/motions/b2b). The Startup overrides a default only where it differs. An improved default in the Startup Template reaches every Startup that has not overridden it. ## The definition is data Every record in this chapter lives in the Startup's namespace on [api.sb](/code/platform/api-sb). Humans and Agents read and write it through the same [Verbs](/business/nouns/verb). Every edit is a [Change](/business/nouns/change), previewed and merged as one unit. Every choice is a [Decision](/business/nouns/decision) that records its options and its reason. That is what makes a Startup operable by someone new. An operator, Human or Agent, reads the definition and knows who is served, who holds what, and who decides next. ## Next [Customers and hypothesis](/business/record/customers-and-hypothesis): whom the Startup serves, and the belief it sets out to prove. # Modeling a Startup URL: /business/record · Id: `page:business/record` > The six parts of a Startup's definition, from identity and customers to ownership, each taught through a worked example. A [Startup](/business/nouns/startup)'s definition says who it serves, what it sells, how it earns, who acts, and who owns it. These six chapters model each part, each through a different example business. # Ownership and lifecycle URL: /business/record/ownership-and-lifecycle · Id: `page:business/record/ownership-and-lifecycle` > Who holds a Startup, the Lifecycle states it moves through, how a pivot works, and what every transition preserves. Every [Startup](/business/nouns/startup) has an owner of record and a [Lifecycle](/business/nouns/lifecycle). Ownership says who holds its rights, the Lifecycle says what it is doing, and a change to one never rewrites the other. ## The owner of record Every Startup has a legal entity behind it. A Startup the [Studio](/business/nouns/studio) builds is held by the Studio's holding [Company](/business/nouns/company), which is its owner of record; the Studio's officer desk signs for it. A self-serve Startup, created on [startups.new](/start/startups-new) or with `npm create startups`, connects its founder's own entity through a connected Stripe account. The holder of that account is the owner of record, and Stripe verifies who they are. Ownership and operation stay separate. An officer who signs an [Agreement](/business/nouns/agreement) gains no operating [Permission](/business/nouns/permission), and the [Agents](/business/nouns/agent) that run the Startup own nothing. ## Nine states A Startup is always in exactly one state. Five mark progress from an [Idea](/business/nouns/idea) to a compounding business; four mark a different course. | State | The Startup | | --- | --- | | [Idea](/business/lifecycle/states/idea) | States its Idea and who pays, before any build work | | [Building](/business/lifecycle/states/building) | Has Agents building its [Brand](/business/nouns/brand), [Products](/business/nouns/product), [Offers](/business/nouns/offer), [Site](/business/nouns/site), and API | | [Live](/business/lifecycle/states/live) | Is publicly reachable and takes money for at least one Offer | | [Repeatable](/business/lifecycle/states/repeatable) | Wins, serves, and keeps [Customers](/business/nouns/customer) with no person in the loop | | [Scale](/business/lifecycle/states/scale) | Compounds: Customers expand, demand diversifies, margins hold | | [Hold](/business/lifecycle/states/hold) | Keeps serving Customers while its owner adds no new investment | | [Graduate](/business/lifecycle/states/graduate) | Leaves its Studio for a Company of its own | | [Sell](/business/lifecycle/states/sell) | Has an agreed sale to a new owner | | [Dormant](/business/lifecycle/states/dormant) | Runs no work; its records, Site, and [Domain](/business/nouns/domain) stay kept | Each state has entry checks, and the checks read [Evidence](/business/nouns/evidence) and [Metrics](/business/nouns/metric), never typed-in fields. reliefvet.app, a marketplace that books licensed relief veterinarians into clinics, entered Building only once outside clinics had placed refundable deposits. ## What every transition keeps A transition changes what the Startup is doing, never what it is. Its identity, Customers, Agreements, Domains, records, and financial history carry through every state. Nothing is deleted. A retired Offer stops new purchases, while its open [Orders](/business/nouns/order), [Subscriptions](/business/nouns/subscription), and remedies run to their end. ## Pivots A pivot is a [Change](/business/nouns/change) to the founding [Hypothesis](/business/nouns/hypothesis), named for the slot it moved. It is a diff between two versions of one sentence, and the Startup stays the same Startup. reliefvet.app began with general practice clinics. Emergency hospitals filled shifts three times faster and paid 40% more per shift, so it moved its customer slot to emergency hospitals. Before the Change merged, its preview showed every compiled output it touched: the Site's headline, two Offers, and the demand [Plays](/business/nouns/play). The old version kept its Evidence, the [Decision](/business/nouns/decision) recorded why, and every open shift Agreement stayed in force. ## Hold and dormancy Hold is an operating choice, not a failure. The Startup keeps serving Customers and meeting its Agreements while new investment stops. A hold records which monitoring stays on, which spending stops, and what Evidence would justify investing again. reliefvet.app on hold still books every shift a clinic requests, but runs no paid demand. Dormant goes further: no work runs at all. A Startup enters it only once its open obligations are fulfilled or transferred, so dormancy never strands a Customer. A Dormant Startup can return to Live. ## Graduating and selling To graduate, a Startup moves to a Company of its own. Forming that Company and issuing its equity is legal work; the Brand, Customers, records, and operating definition move intact. A sale transfers a coherent package to the buyer: - Products, Offers, and the Customers who accepted them - Agreements, including those with every [Supplier](/business/nouns/supplier) - Domains, the Brand, and its rights - Records, Decisions, and financial history - Every shared dependency, named with its [Price](/business/nouns/price) and term For a marketplace, supply is half the asset. A buyer of reliefvet.app receives each veterinarian's Agreement and [Credential](/business/nouns/credential) records along with the clinics. Anything the Startup buys from a sibling or runs on Studio [Systems](/business/nouns/system) is listed with its terms, so nothing it relies on stays hidden. ## Next [Identity and structure](/business/record/identity-and-structure) reads differently with the Lifecycle in mind, and the [Lifecycle chapters](/business/lifecycle) follow each state in depth. # Strategy, Goals, and economics URL: /business/record/strategy-goals-and-economics · Id: `page:business/record/strategy-goals-and-economics` > How a Startup turns one number into dated Goals, chooses Plays to reach them, and judges each choice by the unit economics it produces. Strategy is the set of choices a [Startup](/business/nouns/startup) makes about whom to serve, what to offer, and where to spend. [Goals](/business/nouns/goal) state what those choices must produce; [Metrics](/business/nouns/metric) report whether they did. ## One number at the root Every Startup starts from one number: its minimum success criteria. It is a Goal with a single [Key Result](/business/nouns/key-result), outside revenue by a date, and its default comes from a [Studio](/business/nouns/studio) [Setting](/business/nouns/setting). parsepaper.dev sells an API that turns scanned invoices into structured records, priced per page to developers. Its [Founder](/agents/founding/founder) sets $5,000 a month in outside revenue within six months. The number back-solves into a plan before anything is built. Each step divides by a rate, so a weak rate shows up as an impossible volume. | Step | Rate | Needed | | --- | --- | --- | | Outside revenue | The minimum success criteria | $5,000 | | Paying developers | $40 average spend each | 125 | | Trials | 4% of trials convert to paid | 3,125 | | [Visitors](/business/nouns/visitor) to the docs | 10% start a trial | 31,250 | If no affordable mix of [Plays](/business/nouns/play) brings 31,250 developers a month to the docs, the model fails on paper, for free. If one does, each row becomes a dated Key Result, and together they chart the path to the number. ## Four records kept apart A finished task list is not a Goal met. Four distinct records keep the gap visible. | Record | What it holds | parsepaper.dev | | --- | --- | --- | | Goal | An objective with one or more Key Results | Make self-serve signup repeatable | | Key Result | A Metric, a baseline, a target, and a deadline | Paying developers, from 40 to 125, by the end of the quarter | | Metric | A measure computed from [Events](/business/nouns/event) or [Entries](/business/nouns/entry) | Paying developers in the trailing 30 days | | [Task](/business/nouns/task) | One piece of work | Publish the quickstart for the [SDK](/code/sdk/reference) | Publishing a quickstart is work; more paying developers is the result. A Metric is always derived from recorded Events, never typed in, so nobody meets a Key Result by editing a number. ## Choices become Decisions and Plays parsepaper.dev chooses developers at small accounting software companies over enterprise finance teams. That one choice sets which demand to pursue, how much to invest in support, and which [Evidence](/business/nouns/evidence) matters. Each choice is a [Decision](/business/nouns/decision): the options, the choice, the reason, and who decided. It stands until a later Decision supersedes it, so strategy changes by record, never by drift. A Play turns a choice into repeatable work. It names what to do, the Metric it moves, and its cost, and the Startup runs it as a [Process](/business/nouns/process). parsepaper.dev runs three demand Plays that cost no cash: [Developer relations](/workflows/plays/developer-relations), [Open source](/workflows/plays/open-source) parsers for two common invoice formats, and [Agent registries](/workflows/plays/agent-registries). A long-tail Startup spends $0 on demand by default. A founder can fund a demand budget at any amount. That spend is an investment Decision with a target and a stop rule, and it runs under [Limits](/business/nouns/limit). ## Economics of one unit Every Startup knows what one unit of its work earns. For parsepaper.dev, the unit is 1,000 pages parsed. | Line | Amount | | --- | --- | | Fee | $12.00 | | Model inference | −$3.90 | | Storage and compute | −$0.50 | | Retries on unreadable scans | −$0.70 | | Payment fees | −$0.65 | | Support | −$0.35 | | Contribution | $5.90 | Each line can sink the business on its own. A cheap model that misreads totals turns every saving into retries and refunds. The payback test joins acquisition to contribution. A developer spending $40 a month contributes about $19.70. If a paid probe wins developers at $60 each, payback takes three months; [Repeatable](/business/lifecycle/states/repeatable) requires one month or less. ## Estimates and readings Before launch, every number above is an estimate inside a [Hypothesis](/business/nouns/hypothesis). After launch, readings replace estimates line by line. Each figure keeps its provenance: estimate or reading, with its source and window. A margin that blends the two hides which half is wrong. A Metric names its definition, population, window, and source. Without them it answers the wrong question with false precision. ## Experiments decide Every [Change](/business/nouns/change) to an [Offer](/business/nouns/offer), [Price](/business/nouns/price), [Page](/business/nouns/page), message, or Play can run as an [Experiment](/business/nouns/experiment). It varies copy or behavior through [Flags](/business/nouns/flag) and judges the variants by one primary Metric, with guardrail Metrics that stop it at once. Price is the exception: the same Offer never shows two Prices in one market. parsepaper.dev tests $15 against $12 by geography, charging $15 to new developers in one region for four weeks. Conversion holds within two points and revenue per developer rises 22%, so $15 becomes the list Price everywhere. The losing variant concludes with its Evidence kept, and the winner becomes the definition. ## Allocation and holding The Studio compares Startups by these results and allocates attention and money across its [Portfolio](/business/nouns/portfolio). A small profitable Startup and a fast-growing one earn different allocations, each on its own numbers. Holding is a valid choice. When no available action has a justified return, a Startup enters [Hold](/business/lifecycle/states/hold): it keeps serving [Customers](/business/nouns/customer) while its owner adds no new investment. ## Next Which [Role](/business/nouns/role) owns each Goal, and with what authority: [Roles and responsibility](/agents/roles-and-responsibility). # Relationships URL: /business/relationships · Id: `page:business/relationships` > How the Nouns of a business connect, each relationship declared once and read as a sentence from both ends. A [Relationship](/business/nouns/relationship) is a standing link between two records, declared once and read from both ends. A [Startup](/business/nouns/startup) `makes` many [Products](/business/nouns/product), and each Product is `madeBy` its Startup. # Reserve-first URL: /business/reserve-first · Id: `page:business/reserve-first` > The first test every Startup runs is a refundable deposit on a reserve page published on day one, which settles the switch slot with money. Reserve-first is the first test every [Startup](/business/nouns/startup) runs: a refundable deposit on a reserve page, published the day the Startup is created. It settles the switch slot with money, the one answer politeness cannot fake. ## Why money first When building costs almost nothing, the risk left is building what nobody wants. A hundred people who call an [Idea](/business/nouns/idea) great have bought nothing, so Opinion weighs zero. A deposit is Commitment: the buyer gives something up. Commitment from outside buyers on the customer, problem and switch slots opens [Building](/business/lifecycle/states/building), and deposits are its fastest source. ## Compiled on day one The reserve page is the first output the [Founding Hypothesis](/business/founding-hypothesis) compiles. Nobody writes it. | Part of the page | Compiled from | | --- | --- | | Headline | the problem slot, in the words of the [ICP](/business/nouns/icp) | | [Offer](/business/nouns/offer) | the approach slot and its [Product Template](/business/nouns/product-template) | | [Price](/business/nouns/price) | a share of what the ICP hires today, from the switch slot | | Ship date | the date the approach can deliver, inside the first [Key Result](/business/nouns/key-result) of the [Minimum Success Criteria](/business/nouns/minimum-success-criteria) | | Disclosure | the [legal floor](/systems/legal-and-corporate/floor): the [Product](/business/nouns/product) is not built, and the page names the ship date | ## Terms that keep a deposit honest A deposit refunds in full on request, at any time before the ship date. If the Startup misses the date, every deposit refunds automatically. At ship, the deposit pays the first [Invoice](/business/nouns/invoice). Refund terms are the same for every reserver. No [Experiment](/business/nouns/experiment) varies them, and a Price test runs as a sibling Offer to new buyers. ## Reading the result The threshold is fixed before the page goes live: how many deposits, from how many people reached, by what date. Nobody moves it after the first [Visitor](/business/nouns/visitor) arrives. Only outside buyers count. A deposit from the [Founder](/agents/founding/founder), the [Studio](/business/nouns/studio) or a sibling Startup is kept on the record and never passes a gate. A miss is a result: every reserver is refunded, and the [Decision](/business/nouns/decision) records what the week settled. ## Write it The page compiles from the Founding Hypothesis, so `startup.ts` holds only the two values nothing else can supply: the ship date and the threshold. The deposit defaults to the first period of the Price, and no field sets the refund terms. ```ts import { Startup } from 'startup-builder' export default Startup({ name: 'Platecost', domain: 'platecost.app', extends: 'solo-saas', hypothesis: { /* the five slots */ }, reserve: { ships: '2027-01-15', threshold: { deposits: 8, reached: 40, by: '2026-11-05' }, }, }) ``` Creating the Startup compiles the reserve Offer as `offer_1`. Rehearse its publish to read the page before anyone sees it: **API** ```bash curl -X POST "https://api.sb/platecost.app/offers/offer_1/publish?mode=try" \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` **SDK** ```ts import { $ } from 'startup-builder' const preview = await $.Offer.publish({ offer: 'offer_1' }, { mode: 'try' }) ``` **CLI** ```bash npx startup-builder do Offer.publish --json '{"offer":"offer_1"}' --try ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Offer.publish({ offer: 'offer_1' })", "mode": "try" } } ``` ```text try Offer.publish offer_1, reserve nothing written Headline Stop rebuilding the food-cost sheet every weekend. from: Hypothesis#problem@v1 Offer Plate costs from every invoice you photograph from: Hypothesis#approach@v1 Price $79 a month, $79 refundable deposit from: Hypothesis#switch@v1 Ships 2027-01-15 inside Key Result 2 Disclosure Platecost is not built. It ships 2027-01-15. legal floor Threshold 8 deposits from 40 reached, by 2026-11-05 fixed at publish ``` Run it without `--try` to put the page live. Once it is live, the threshold takes no edit. To read the result, ask for the record: ```bash npx startup-builder show /reserve ``` ```text platecost.app reserve page live since 2026-10-22 reached 40 outside ICP members sent to the page deposits 9 outside, $711 held excluded 1 the Founder's deposit, kept on the record threshold 8 by 2026-11-05 passed 2026-11-02 grade switch at Commitment, from 9 deposits ``` ## Next - [Reserve](/products/selling/reserve): the Offer, the [Order](/business/nouns/order) and the conversion at ship. - [Wants](/code/builders/startup/wants): the unmet demand that sends people to the page. - [Test ladder](/business/test-ladder): the rungs above and below a pre-sale. # Start a business URL: /business/start-a-business · Id: `guide:start-a-business` > Say what the business does and what it charges, and get a Startup with its app, Site, domain, Offer, Stripe account, Teams, Roles and Systems. One sentence creates a [Startup](/business/nouns/startup) from a [Startup Template](/business/nouns/startup-template) and builds it: `Startup.create` records the business, and [`Startup.build`](/business/nouns/startup/build) provisions what it declares. **Before it runs** - You leave the chat: Never: it all happens in the chat. - First question at Idea: “Who is it for, and what does it charge?” - First question at Live: “Start from this business, or from a template?” ## What you get - 1 business named Leaseline, moved from Idea to Building (Startup) - 1 brand: name, logo, colors and voice (Brand) - 1 app your customers sign in to (App) - 1 site at leaseline.app with pricing, sign-up and terms (Site) - 1 domain with its DNS records and certificate (Domain) - 1 Offer at $29 a month, ready to publish (Offer) - 1 Stripe account in the business’s name, claimed in one step (Stripe's Account) - 1 product and monthly price on Stripe (Stripe's Product and Price) - 4 Interfaces to the business: API, SDK, CLI and MCP server (Interface) - 10 Teams, from Product to Legal (Team) - 38 Roles, an agent named in each (Role) - 56 Processes, each owned by a Role (Process) - 67 Systems: billing, ledger, CRM, support and the rest (System) - 1 connect providers runs on the first day (Workflow) - 1 publish terms runs on the first day (Workflow) - 1 staff roles runs on the first day (Workflow) ## Your agent does **For agents** - Guide: `guide:start-a-business`, status `live`. Page: [/business/start-a-business.md](/business/start-a-business.md). - Approval: none. Run it when the founder asks. - Leaves the chat: never. - Run: call the steps in order, each through the API, SDK, CLI or MCP tab below; a later step passes the `$id` an earlier one returns. Each value marked example is the sample business’s: pass the founder’s own. | Step | Verb | Inputs (type, required, this guide’s value) | Returns | | --- | --- | --- | --- | | 1 | [`Startup.create`](/business/nouns/startup/create) (`verb:Startup.create`) | `name` string, required: example `"Leaseline"`; `idea` text: example `"Tracks lease renewals for small property managers, $29 a month."` | `startup` Startup | | 2 | [`Startup.build`](/business/nouns/startup/build) (`verb:Startup.build`) | `startup` Startup (an id), required: the `$id` step 1 returns | `startup` Startup | Returns: the last call answers with `startup` and its `action`, whose `status` is `done`, `pending` (waiting on an Approval or a Worker), `failed`, `canceled` or `refused`: ```json { "api": "https://api.sb/leaseline.app", "startup": { "$id": "https://api.sb/leaseline.app/startups/startup_1", "$type": "Startup", "name": "Leaseline", "idea": "Tracks lease renewals for small property managers, $29 a month." }, "action": { "$id": "https://api.sb/leaseline.app/actions/action_1", "operation": "Startup.build", "status": "done" }, "links": { "self": "https://api.sb/leaseline.app/actions/action_1" } } ``` Next: offer “Call it Renewly instead”, or “Charge $49 a month for up to 500 units”. Calls: `Startup.create` → `Startup.build` Ask: ```text Start a business that tracks lease renewals for small property managers, $29 a month. Make me a business for landlords who keep missing renewal dates. Turn my idea into a business: renewal reminders for managers with up to 200 units. ``` API: ```bash # 1. Startup.create STARTUP=$(curl -X POST https://api.sb/leaseline.app/startups \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"name":"Leaseline","idea":"Tracks lease renewals for small property managers, $29 a month."}' | jq -r '.startup["$id"] | split("/") | last') # 2. Startup.build curl -X POST https://api.sb/leaseline.app/startups/$STARTUP/build \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` SDK: ```ts import { $ } from 'startup-builder' const startup = await $.Startup.create({ name: 'Leaseline', idea: 'Tracks lease renewals for small property managers, $29 a month.' }) await $.Startup.build({ startup: startup.$id }) ``` CLI: ```bash STARTUP=$(npx startup-builder do Startup.create --json '{"name":"Leaseline","idea":"Tracks lease renewals for small property managers, $29 a month."}' | jq -r '.startup["$id"] | split("/") | last') npx startup-builder do Startup.build --json '{"startup":"'"$STARTUP"'"}' ``` MCP: ```json { "name": "do", "arguments": { "code": "const startup = await $.Startup.create({ name: 'Leaseline', idea: 'Tracks lease renewals for small property managers, $29 a month.' })\nreturn await $.Startup.build({ startup: startup.$id })" } } ``` ## Change it - Call it Renewly instead. - Charge $49 a month for up to 500 units. - Sell to agencies as well as landlords. - Use the Solo SaaS template instead. ## Under the hood - Systems: [Sites](/products/site/sites), [Billing](/systems/billing), [Ledger](/systems/ledger), [CRM](/systems/crm), [Support](/systems/support) - Nouns: [Startup](/business/nouns/startup), [Brand](/business/nouns/brand), [App](/business/nouns/app), [Site](/business/nouns/site), [Domain](/business/nouns/domain), [Offer](/business/nouns/offer), [Team](/business/nouns/team), [Role](/business/nouns/role) - Events: `Startup.created`, [`Startup.built`](/business/events/Startup.built) - Stripe objects: `Account`, `Product`, `Price` # The Startup URL: /business/startup · Id: `page:business/startup` > A Startup is the smallest business that can be moved, promoted, or sold on its own, with its own Products, Offers, Customers, and P&L. A [Startup](/business/nouns/startup) is one business defined as code. It holds what the business sells, who it serves, who runs it and the software it runs on. ## What you get One sentence on [startups.new](/start/startups-new), or `npm create startups`, creates a Startup with all of this. - 1 business named Leaseline, moved from Idea to Building (Startup) - 1 brand: name, logo, colors and voice (Brand) - 1 app your customers sign in to (App) - 1 site at leaseline.app with pricing, sign-up and terms (Site) - 1 domain with its DNS records and certificate (Domain) - 1 Offer at $29 a month, ready to publish (Offer) - 1 Stripe account in the business’s name, claimed in one step (Stripe's Account) - 1 product and monthly price on Stripe (Stripe's Product and Price) - 4 Interfaces to the business: API, SDK, CLI and MCP server (Interface) - 10 Teams, from Product to Legal (Team) - 38 Roles, an agent named in each (Role) - 56 Processes, each owned by a Role (Process) - 67 Systems: billing, ledger, CRM, support and the rest (System) - 1 connect providers runs on the first day (Workflow) - 1 publish terms runs on the first day (Workflow) - 1 staff roles runs on the first day (Workflow) Most of it is ready in the first minute. [What gets set up, in order](/business/provisioning) shows the steps that wait on you, Stripe, a registrar or a state. ## Guides - [Start a business](/business/start-a-business): "Start a business that tracks lease renewals for small property managers, $29 a month." - [Launch my business](/business/launch-my-business): "Launch Leaseline." - [Charge monthly](/systems/finance/charge-monthly): "Charge $29 a month." - [Connect my domain](/products/site/domains/connect-my-domain): "Connect leaseline.com. I bought it somewhere else." ## What it holds ## Its states A Startup moves through the states of its [Lifecycle](/business/nouns/lifecycle), from the first idea to scale. Each move runs the entry checks of the next state and wakes the work that state needs. [States](/business/states) draws every move. ## How it works The [business record](/business/record) holds the values the Startup sets for itself, and its [Startup Template](/business/nouns/startup-template) supplies the rest. [StartupBuilder](/code/builders/startup) compiles the definition and directs the four other [Builders](/business/nouns/builder). Each [Product](/business/nouns/product) earns under one of five [earning models](/business/business-models). A Startup is always a new business. To sell an app that already exists, a new Startup wraps the business around it, and a running business is never migrated in place. [`Startup.import`](/business/nouns/startup/import) starts that Startup from an existing business's [Offers](/business/nouns/offer), [Pages](/business/nouns/page) and [Nouns](/business/nouns/noun). # States URL: /business/states · Id: `page:business/states` > Where each record stands in its lifecycle, the Verbs and Events that move it, and the states a Startup moves through from idea to scale. A state is where one record stands: an [Order](/business/nouns/order) is `placed`, `paid` or `refunded`. Only a [Verb](/business/nouns/verb) or an [Event](/business/nouns/event) moves it, and every move is on record. ## The Startup's states A [Startup](/business/nouns/startup) moves through the states of its [Lifecycle](/business/nouns/lifecycle), and each move runs the entry checks of the next state. [Startup.advance](/business/nouns/startup/advance) makes the move and names each check that fails. ## How a record moves Each state lists its ways out. Most are Verbs someone calls, as [`Order.pay`](/business/nouns/order/pay) moves an Order from `placed` to `paid`. The rest are Events with no caller, from the payment rail, the clock or the runtime. When an [Invoice](/business/nouns/invoice) goes overdue, `Invoice.overdue` moves its [Subscription](/business/nouns/subscription) to `pastDue` and nobody calls anything. Three rules hold for every record: - `update` never moves a state. A record changes state only through the Verb or Event its lifecycle names. - A record's `actions` list only the Verbs that move it from where it stands, so an agent that follows them never calls a refused Verb. - A terminal state is final. A refunded Order stays refunded, and a new purchase is a new Order. Some states are computed, never set. A [Customer](/business/nouns/customer) turns `atRisk` when a renewal goes past due or a charge is disputed, and turns back once the Invoice is paid. No Verb takes a computed state as an input. Every move emits an Event whose `data` holds the record as the move left it and `previous` holds the state it left. A [Trigger](/business/nouns/trigger) can wake a [Workflow](/business/nouns/workflow) on that Event, or on a record entering a state. ## Read one lifecycle Each [Noun](/business/nouns/noun) page draws its lifecycle and lists it as a table. The Order's reads like this: | State | Meaning | Moves to | | --- | --- | --- | | `placed` (first) | The Customer committed, with the Offer Version and price fixed; nothing is charged yet. | `paid` by [Order.pay](/business/nouns/order/pay); `canceled` by [Order.cancel](/business/nouns/order/cancel) | | `paid` | Its amount is settled and its Entries posted; a Service Order’s work runs in `fulfillment`. | `fulfilled` by [Order.fulfill](/business/nouns/order/fulfill); `closed` by [Order.confirm](/business/nouns/order/confirm); `canceled` by [Order.cancel](/business/nouns/order/cancel); `refunded` by [Order.refund](/business/nouns/order/refund) | | `fulfilled` | What it bought is granted: Entitlements for software and data, or a shipment for goods. | `closed` by [Order.confirm](/business/nouns/order/confirm); `refunded` by [Order.refund](/business/nouns/order/refund) | | `closed` | The Customer signed off, which earns the Startup its fee. | `refunded` by [Order.refund](/business/nouns/order/refund) | | `canceled` | Ended before fulfillment, with any payment returned in full. | None: it ends here. | | `refunded` | Its payment returned in full, with the reversing Entries posted; a partial refund keeps its state. | None: it ends here. | ## Every record with states These records carry a closed set of states, listed from the first. Each name opens its page, which draws the moves where its Noun has a lifecycle. ## Your own states A Noun the Startup adds gets a lifecycle the same way. Its `status` values are the states and its Verbs are the moves, and [Nouns](/code/file-conventions/nouns) shows the file that declares both. Records of that Noun then show their state on every [Interface](/business/nouns/interface) and emit an Event on every move. # Terms that collide URL: /business/terms · Id: `page:business/terms` > Words that mean two things in other tools, the one meaning each keeps here, and the word to use for the other. Every term in these docs has one meaning. Where another tool, Stripe or the E-Myth uses a word differently, the tables below name the meaning it keeps and the word to use instead. ## Five words, one meaning each Each of these words means two things in other tools. Here it means one, and the other meaning has its own word. | Word | Means here | For the other meaning, say | | --- | --- | --- | | [Founding Team](/agents/founding) | The [Founder](/agents/founding/founder) and the seats that decide what the [Startup](/business/nouns/startup) pursues | "your team" for everyone who works in the Startup, agents and humans | | [Policy](/business/nouns/policy) | A ruling on how numbers are computed, such as revenue recognition | [Conduct](/systems/trust-and-governance/controls/conduct) for the rules every [Worker](/business/nouns/worker) acts under, enforced by [Guards](/business/nouns/guard) | | Run | Nothing. One execution of a [Workflow](/business/nouns/workflow) is an [Action](/business/nouns/action), with a status and its [Events](/business/nouns/event) | Action | | [Role](/business/nouns/role) | A seat that owns work, filled by an [Agent](/business/nouns/agent) or a [Human](/business/nouns/human) | [Access Level](/business/nouns/access-level) for a preset of [Permissions](/business/nouns/permission), such as owner or viewer | | Scorecard | Nothing. The weekly check of every seat is the [Role review](/workflows/processes/role-review) [Process](/business/nouns/process), which records one [Role Review](/business/nouns/role-review) per filled Role | Role review | A founder who says "give her admin" means an Access Level. A founder who says "hire a bookkeeper" means a Role, and the [Finance Lead](/agents/finance/finance-lead) seat answers to that name. ## One word each | These look alike | The difference | | --- | --- | | Startup, [Company](/business/nouns/company) | A Startup is one business with its own P&L. A Company is the legal entity that holds one or more Startups. | | [Product](/business/nouns/product), [Offer](/business/nouns/offer), [Price](/business/nouns/price) | A Product is what the [Customer](/business/nouns/customer) gets. An Offer sells a Product at a Price on terms. A Price lives inside its Offer. | | [Contact](/business/nouns/contact), [Lead](/business/nouns/lead), Customer, [Persona](/business/nouns/persona) | A Contact is someone the Startup can reach. A Lead raised a hand. A Customer accepted an Offer. A Persona is a type of person, never a record of one. | | Process, Workflow, [Play](/business/nouns/play) | A Process is repeatable business work a [Team](/business/nouns/team) owns. A Workflow is the code that runs one Action of it. A Play is a strategy run as a Process. | | [System](/business/nouns/system), [Integration](/business/nouns/integration), [Capability](/business/nouns/capability) | A System is the software for one job, such as billing. An Integration connects an outside account to a System. A Capability is a metered set of [Verbs](/business/nouns/verb) every Startup calls. | | [Account](/business/nouns/account), [Tenant](/business/nouns/tenant) | An Account is a line in the chart of accounts. A Customer's own space in the product, with its people and data, is a Tenant. | | Event, [Gathering](/business/nouns/gathering) | An Event is the record that something happened. A webinar or a meetup is a Gathering. | ## Stripe's names Stripe holds the money side of every Startup, and some of its words name different things here. Stripe's `Product` is an Offer, because Stripe sells what an Offer sells. A charge, a payout and a refund are each a [Transaction](/business/nouns/transaction) with that `kind`. | Noun | Stripe object | When | Source of truth | | --- | --- | --- | --- | | [Account](/business/nouns/account) | **Treasury FinancialAccount** (`treasury.financial_account`) | `heldAt` is `treasury` | Stripe | | [Card](/business/nouns/card) | **Issuing Card** (`issuing.card`) | Always | db.sb | | [Customer](/business/nouns/customer) | **Customer** (`customer`) | Always | db.sb | | [Dispute](/business/nouns/dispute) | **Dispute** (`dispute`) | `kind` is `chargeback` | Stripe | | [Invoice](/business/nouns/invoice) | **Invoice** (`invoice`) | Always | db.sb | | [Offer](/business/nouns/offer) | **Product** (`product`) | Always | db.sb | | [Price](/business/nouns/price) | **Price** (`price`) | Always | db.sb | | [Subscription](/business/nouns/subscription) | **Subscription** (`subscription`) | Always | db.sb | | [Transaction](/business/nouns/transaction) | **PaymentIntent** (`payment_intent`) | `kind` is `charge` | Stripe | | [Transaction](/business/nouns/transaction) | **Payout** (`payout`) | `kind` is `payout` | Stripe | | [Transaction](/business/nouns/transaction) | **Refund** (`refund`) | `kind` is `refund` | Stripe | Stripe's field names keep Stripe's casing and appear only in these mappings. Every call here takes camelCase. ## The E-Myth's names Michael Gerber's E-Myth runs a business through seats, each with a contract, and through routines that make the work repeatable. Teams and Roles here follow that shape, and two words change. | E-Myth | Here | | --- | --- | | org chart | [Teams](/agents) and the Roles in each | | position contract | The Role contract on every Role page | | a system for doing the work | A Process, run by Workflows | | the owner who works on the business | The Founder, who holds the [Approvals](/business/nouns/approval), not the seats | A System here is software. The E-Myth's "system" is a Process. # Test ladder URL: /business/test-ladder · Id: `page:business/test-ladder` > Every way to grade a Hypothesis, cheapest first, and the rule that sends each one to the lowest rung that can settle it. The test ladder lists every way to grade a [Hypothesis](/business/nouns/hypothesis), cheapest first. Each Hypothesis goes to the lowest rung that can yield the grade its threshold needs. ## The rungs Each rung has a typical cost, a time to a [Readout](/business/nouns/readout), and the strongest [Evidence](/business/nouns/evidence) grade it can yield. | Rung | Cost | Latency | Strongest grade | Reaches people | What it does | | --- | --- | --- | --- | --- | --- | | Prior lookup | $0 | 1h | Opinion | No | Prior lookup reads what the Portfolio already learned about the same Product Template, Motion and state. | | Offline replay | $0 | 4h | Opinion | No | Offline replay scores a Variant on the kept log of past choices before anyone sees it. | | Interview | $0 | 3d | Commitment | Yes | Interview asks ICP members about the last time the Problem hit, and counts the introductions and time they offer. | | Smoke page | $0 | 1w | Behavior | Yes | Smoke page publishes an Offer at its real Price before it delivers and counts who tries to accept. | | Fake door | $0 | 1w | Behavior | Yes | Fake door adds a coming-soon Offer to a live Site and counts the clicks on it. | | Pre-sale | $0 | 2w | Commitment | Yes | Pre-sale takes a refundable deposit on a reserve page, priced against what the ICP hires today. | | Concierge | $100 | 2w | Behavior | Yes | Concierge delivers the outcome by hand to a few paying Customers, in the open. | | Wizard of Oz | $100 | 2w | Behavior | Yes | Wizard of Oz delivers behind the product’s real interface while people do the work. | | Paid probe | $100 | 1w | Behavior | Yes | Paid probe spends $100 on one ad venue to measure what a click and a Customer cost. | | Single capability | $100 | 4w | Behavior | Yes | Single capability ships the one capability the approach rests on and measures use. | | Flag split | $0 | 2w | Behavior | Yes | Flag split randomizes Variants of the built thing behind a Flag and reads each against the control. | ## The cheapest decisive rung A rung is decisive when its strongest grade meets the threshold. Among decisive rungs, the Hypothesis takes the one with the lowest cost per day to a verdict. The two rungs that reach no one run first, on every Hypothesis. They grade Opinion, so they prune weak candidates and never pass a gate. A Prior lookup that finds the question settled across the [Portfolio](/business/nouns/portfolio) opens the Hypothesis at `Testing`, not `Open`. ## Where each slot starts | Slot | Grade it needs | Cheapest decisive rung | | --- | --- | --- | | customer | Commitment | [Interview](/business/nouns/interview): introductions and time offered | | problem | Commitment | Interview: the last time the [Problem](/business/nouns/problem) hit | | approach | Behavior | Smoke page at the real [Price](/business/nouns/price) | | switch | Commitment | Pre-sale: a [reserve-first](/business/reserve-first) deposit | | differentiation | Behavior | Fake door, one per axis | Before [Live](/business/lifecycle/states/live), the ladder settles most questions in days. A [Flag](/business/nouns/flag) split waits for a built thing and the traffic to read it. ## Lines fixed before the first exposure Every test states its pass and kill lines before anyone sees it: the [Metric](/business/nouns/metric), the window and the minimum sample. A line can tighten after launch and never loosen. [Test demand](/workflows/processes/test-demand) runs the rung and records the verdict. ## Next [Experimentation](/business/experimentation) explains why every run is a test, and what no test varies. # accept URL: /business/verbs/accept · Id: `page:business/verbs/accept` > Every accept Verb, one per Noun: Dispute, Offer, Quote, Risk. `accept` acts on 4 [Nouns](/business/nouns/noun). Each is its own [Verb](/business/nouns/verb), named for its Noun. | Verb | Noun | Definition | | --- | --- | --- | | [Dispute.accept](/business/nouns/dispute/accept) | [Dispute](/business/nouns/dispute) | Accept concedes an open Dispute without contest, so the buyer keeps the held amount and the Dispute closes. | | [Offer.accept](/business/nouns/offer/accept) | [Offer](/business/nouns/offer) | Accept records that a party takes an Offer, which makes that party a Customer of the Startup. | | [Quote.accept](/business/nouns/quote/accept) | [Quote](/business/nouns/quote) | Accept takes a sent Quote before it expires, turning one-time lines into an Order and recurring lines into a Subscription. | | [Risk.accept](/business/nouns/risk/accept) | [Risk](/business/nouns/risk) | Accept records an officer’s signed Decision to carry a Risk untreated until its next review. | # answer URL: /business/verbs/answer · Id: `page:business/verbs/answer` > Every answer Verb, one per Noun: Action, Conversation, Dispute. `answer` acts on 3 [Nouns](/business/nouns/noun). Each is its own [Verb](/business/nouns/verb), named for its Noun. | Verb | Noun | Definition | | --- | --- | --- | | [Action.answer](/business/nouns/action/answer) | [Action](/business/nouns/action) | Answer gives the reply to an Action’s open Question, through any Interface, and the Action resumes. | | [Conversation.answer](/business/nouns/conversation/answer) | [Conversation](/business/nouns/conversation) | Answer replies in a Conversation through the Channel it arrived on and closes the reply Task it opened. | | [Dispute.answer](/business/nouns/dispute/answer) | [Dispute](/business/nouns/dispute) | Answer submits the seller’s Evidence on an open Dispute before its deadline: the contract, the delivered work, and its verdicts. | # approve URL: /business/verbs/approve · Id: `page:business/verbs/approve` > Every approve Verb, one per Noun: Approval, Bill, Pay Run, Registration. `approve` acts on 4 [Nouns](/business/nouns/noun). Each is its own [Verb](/business/nouns/verb), named for its Noun. | Verb | Noun | Definition | | --- | --- | --- | | [Approval.approve](/business/nouns/approval/approve) | [Approval](/business/nouns/approval) | Approve allows the pending Action an Approval holds, and that Action runs. | | [Bill.approve](/business/nouns/bill/approve) | [Bill](/business/nouns/bill) | Approve accepts a coded Bill for payment within the approver’s Mandate and schedules it for its due date. | | [PayRun.approve](/business/nouns/pay-run/approve) | [Pay Run](/business/nouns/pay-run) | Approve accepts a prepared Pay Run within the approver’s Mandate, books its cost, and schedules payment to land on the pay date. | | [Registration.approve](/business/nouns/registration/approve) | [Registration](/business/nouns/registration) | Approve gives a requested place at a Gathering to the Contact who asked, or a place in line when the Gathering is full. | # assign URL: /business/verbs/assign · Id: `page:business/verbs/assign` > Every assign Verb, one per Noun: Conversation, Deal, Lead, Task. `assign` acts on 4 [Nouns](/business/nouns/noun). Each is its own [Verb](/business/nouns/verb), named for its Noun. | Verb | Noun | Definition | | --- | --- | --- | | [Conversation.assign](/business/nouns/conversation/assign) | [Conversation](/business/nouns/conversation) | Assign routes a Conversation to the Worker holding the right Role, by topic, Customer tier and language. | | [Deal.assign](/business/nouns/deal/assign) | [Deal](/business/nouns/deal) | Assign gives a Deal one owner Worker, who carries its next step until it is won or lost. | | [Lead.assign](/business/nouns/lead/assign) | [Lead](/business/nouns/lead) | Assign gives a Lead one owner Worker, by round robin, territory or ICP fit, as the Startup’s routing Policy says. | | [Task.assign](/business/nouns/task/assign) | [Task](/business/nouns/task) | Assign gives a Task to a Worker, human or agent, and places it in that Worker’s worklist. | # cancel URL: /business/verbs/cancel · Id: `page:business/verbs/cancel` > Every cancel Verb, one per Noun: Action, Enrollment, Instrument, Order. `cancel` acts on 4 [Nouns](/business/nouns/noun). Each is its own [Verb](/business/nouns/verb), named for its Noun. | Verb | Noun | Definition | | --- | --- | --- | | [Action.cancel](/business/nouns/action/cancel) | [Action](/business/nouns/action) | Cancel stops a pending Action, sets its status to `canceled`, and runs its compensation. | | [Enrollment.cancel](/business/nouns/enrollment/cancel) | [Enrollment](/business/nouns/enrollment) | Cancel ends one Contact’s run through a Sequence for good, with the reason it records as `exitReason`. | | [Instrument.cancel](/business/nouns/instrument/cancel) | [Instrument](/business/nouns/instrument) | Cancel ends an unvested, expired or forfeited Instrument and returns any option Shares to the pool. | | [Order.cancel](/business/nouns/order/cancel) | [Order](/business/nouns/order) | Cancel ends an Order before fulfillment and returns any payment in full. | # claim URL: /business/verbs/claim · Id: `page:business/verbs/claim` > Every claim Verb, one per Noun: Domain, Startup, Task. `claim` acts on 3 [Nouns](/business/nouns/noun). Each is its own [Verb](/business/nouns/verb), named for its Noun. | Verb | Noun | Definition | | --- | --- | --- | | [Domain.claim](/business/nouns/domain/claim) | [Domain](/business/nouns/domain) | Claim gives a Startup a one-label name under an issuing Domain, or assigns it a held Domain through an approved Change. | | [Startup.claim](/business/nouns/startup/claim) | [Startup](/business/nouns/startup) | Claim binds a provisional Startup to a verified owner, which enables payments and every Verb that moves money. | | [Task.claim](/business/nouns/task/claim) | [Task](/business/nouns/task) | Claim takes an offered Task from a shared queue or a handoff and makes the calling Worker its assignee. | # close URL: /business/verbs/close · Id: `page:business/verbs/close` > Every close Verb, one per Noun: Conversation, Period, Risk. `close` acts on 3 [Nouns](/business/nouns/noun). Each is its own [Verb](/business/nouns/verb), named for its Noun. | Verb | Noun | Definition | | --- | --- | --- | | [Conversation.close](/business/nouns/conversation/close) | [Conversation](/business/nouns/conversation) | Close marks a Conversation resolved, confirmed by the Customer or assumed after 72 hours with no reply. | | [Period.close](/business/nouns/period/close) | [Period](/business/nouns/period) | Close ends a month’s books once every Entry in the Period is reconciled, and makes its statements final. | | [Risk.close](/business/nouns/risk/close) | [Risk](/business/nouns/risk) | Close ends a Risk that can no longer happen and keeps it, with its scores and treatments, forever. | # connect URL: /business/verbs/connect · Id: `page:business/verbs/connect` > Every connect Verb, one per Noun: Domain, Handle, Integration. `connect` acts on 3 [Nouns](/business/nouns/noun). Each is its own [Verb](/business/nouns/verb), named for its Noun. | Verb | Noun | Definition | | --- | --- | --- | | [Domain.connect](/business/nouns/domain/connect) | [Domain](/business/nouns/domain) | Connect attaches a hostname a Startup already holds and verifies ownership through DNS. | | [Handle.connect](/business/nouns/handle/connect) | [Handle](/business/nouns/handle) | Connect binds a Handle to the Integration credential it publishes through, once the platform confirms the account. | | [Integration.connect](/business/nouns/integration/connect) | [Integration](/business/nouns/integration) | Connect asks an account holder to approve an outside account for one System and records the grants they approve. | # Verbs URL: /business/verbs · Id: `page:business/verbs` > The Verbs three or more Nouns share, by family; every other Verb lives on its Noun page. A [Verb](/business/nouns/verb) is named for the [Noun](/business/nouns/noun) it acts on: `Noun.verb`, and each Noun page lists its own. A name three or more Nouns share has a page here. | Family | Verb | On | | --- | --- | --- | | lifecycle | [`cancel`](/business/verbs/cancel) | [Order](/business/nouns/order/cancel), [Action](/business/nouns/action/cancel), [Instrument](/business/nouns/instrument/cancel), [Enrollment](/business/nouns/enrollment/cancel) | | lifecycle | [`claim`](/business/verbs/claim) | [Startup](/business/nouns/startup/claim), [Task](/business/nouns/task/claim), [Domain](/business/nouns/domain/claim) | | lifecycle | [`close`](/business/verbs/close) | [Period](/business/nouns/period/close), [Risk](/business/nouns/risk/close), [Conversation](/business/nouns/conversation/close) | | lifecycle | [`pause`](/business/verbs/pause) | [Startup](/business/nouns/startup/pause), [Action](/business/nouns/action/pause), [Watch](/business/nouns/watch/pause), [Mandate](/business/nouns/mandate/pause), [Subscription](/business/nouns/subscription/pause), [Integration](/business/nouns/integration/pause), [Process](/business/nouns/process/pause), [Enrollment](/business/nouns/enrollment/pause), [Agent](/business/nouns/agent/pause) | | lifecycle | [`resume`](/business/verbs/resume) | [Startup](/business/nouns/startup/resume), [Action](/business/nouns/action/resume), [Watch](/business/nouns/watch/resume), [Mandate](/business/nouns/mandate/resume), [Subscription](/business/nouns/subscription/resume), [Integration](/business/nouns/integration/resume), [Enrollment](/business/nouns/enrollment/resume), [Agent](/business/nouns/agent/resume) | | lifecycle | [`retire`](/business/verbs/retire) | [Noun](/business/nouns/noun/retire), [Verb](/business/nouns/verb/retire), [Mailbox](/business/nouns/mailbox/retire), [Voice](/business/nouns/voice/retire), [Agent](/business/nouns/agent/retire) | | review | [`approve`](/business/verbs/approve) | [Approval](/business/nouns/approval/approve), [Bill](/business/nouns/bill/approve), [Registration](/business/nouns/registration/approve), [PayRun](/business/nouns/pay-run/approve) | | review | [`screen`](/business/verbs/screen) | [Candidate](/business/nouns/candidate/screen), [Party](/business/nouns/party/screen), [Order](/business/nouns/order/screen) | | communication | [`answer`](/business/verbs/answer) | [Conversation](/business/nouns/conversation/answer), [Dispute](/business/nouns/dispute/answer), [Action](/business/nouns/action/answer) | | money | [`pay`](/business/verbs/pay) | [Order](/business/nouns/order/pay), [Commission](/business/nouns/commission/pay), [Bill](/business/nouns/bill/pay), [PayRun](/business/nouns/pay-run/pay) | | change | [`merge`](/business/verbs/merge) | [Change](/business/nouns/change/merge), [Visitor](/business/nouns/visitor/merge), [Contact](/business/nouns/contact/merge), [Organization](/business/nouns/organization/merge) | | change | [`publish`](/business/verbs/publish) | [Offer](/business/nouns/offer/publish), [App](/business/nouns/app/publish), [Site](/business/nouns/site/publish), [Content](/business/nouns/content/publish), [Post](/business/nouns/post/publish), [Review](/business/nouns/review/publish) | | other | [`accept`](/business/verbs/accept) | [Offer](/business/nouns/offer/accept), [Risk](/business/nouns/risk/accept), [Quote](/business/nouns/quote/accept), [Dispute](/business/nouns/dispute/accept) | | other | [`assign`](/business/verbs/assign) | [Task](/business/nouns/task/assign), [Lead](/business/nouns/lead/assign), [Deal](/business/nouns/deal/assign), [Conversation](/business/nouns/conversation/assign) | | other | [`connect`](/business/verbs/connect) | [Domain](/business/nouns/domain/connect), [Integration](/business/nouns/integration/connect), [Handle](/business/nouns/handle/connect) | | other | [`issue`](/business/verbs/issue) | [Share](/business/nouns/share/issue), [CreditGrant](/business/nouns/credit-grant/issue), [Card](/business/nouns/card/issue), [APIKey](/business/nouns/api-key/issue) | | other | [`register`](/business/verbs/register) | [Domain](/business/nouns/domain/register), [Gathering](/business/nouns/gathering/register), [Company](/business/nouns/company/register) | | other | [`remove`](/business/verbs/remove) | [DNSRecord](/business/nouns/dns-record/remove), [PaymentSource](/business/nouns/payment-source/remove), [Review](/business/nouns/review/remove) | | other | [`resolve`](/business/verbs/resolve) | [Issue](/business/nouns/issue/resolve), [Incident](/business/nouns/incident/resolve), [Thing](/business/nouns/thing/resolve) | | other | [`revoke`](/business/verbs/revoke) | [Mandate](/business/nouns/mandate/revoke), [Integration](/business/nouns/integration/revoke), [Secret](/business/nouns/secret/revoke), [APIKey](/business/nouns/api-key/revoke) | | other | [`schedule`](/business/verbs/schedule) | [Issue](/business/nouns/issue/schedule), [Dashboard](/business/nouns/dashboard/schedule), [Message](/business/nouns/message/schedule), [Post](/business/nouns/post/schedule) | | other | [`void`](/business/verbs/void) | [Invoice](/business/nouns/invoice/void), [CreditGrant](/business/nouns/credit-grant/void), [PayRun](/business/nouns/pay-run/void) | | other | [`withdraw`](/business/verbs/withdraw) | [Offer](/business/nouns/offer/withdraw), [Consent](/business/nouns/consent/withdraw), [Post](/business/nouns/post/withdraw) | # issue URL: /business/verbs/issue · Id: `page:business/verbs/issue` > Every issue Verb, one per Noun: API Key, Card, Credit Grant, Share. `issue` acts on 4 [Nouns](/business/nouns/noun). Each is its own [Verb](/business/nouns/verb), named for its Noun. | Verb | Noun | Definition | | --- | --- | --- | | [APIKey.issue](/business/nouns/api-key/issue) | [API Key](/business/nouns/api-key) | Issue creates an API Key for one Customer and returns its secret once; afterwards only the prefix shows. | | [Card.issue](/business/nouns/card/issue) | [Card](/business/nouns/card) | Issue creates a Card under a Mandate once the Mandate check passes, with explicit limits on every interval. | | [CreditGrant.issue](/business/nouns/credit-grant/issue) | [Credit Grant](/business/nouns/credit-grant) | Issue gives a Customer a paid or promotional Credit Grant that its metered calls draw down before anything is invoiced. | | [Share.issue](/business/nouns/share/issue) | [Share](/business/nouns/share) | Issue records new Shares of one class to a Holder under a board-approved Agreement, with the certificate or book entry. | # merge URL: /business/verbs/merge · Id: `page:business/verbs/merge` > Every merge Verb, one per Noun: Change, Contact, Organization, Visitor. `merge` acts on 4 [Nouns](/business/nouns/noun). Each is its own [Verb](/business/nouns/verb), named for its Noun. | Verb | Noun | Definition | | --- | --- | --- | | [Change.merge](/business/nouns/change/merge) | [Change](/business/nouns/change) | Merge applies a Change to live data with a three-way, field-level merge against its base Version. | | [Contact.merge](/business/nouns/contact/merge) | [Contact](/business/nouns/contact) | Merge joins a duplicate Contact into another, keeping every link, Message and Event on the one that remains. | | [Organization.merge](/business/nouns/organization/merge) | [Organization](/business/nouns/organization) | Merge joins a duplicate Organization into another, keeping every Contact, Deal and Event on the one that remains. | | [Visitor.merge](/business/nouns/visitor/merge) | [Visitor](/business/nouns/visitor) | Merge joins two Visitor ids that belong to one person and keeps both as aliases. | # pause URL: /business/verbs/pause · Id: `page:business/verbs/pause` > Every pause Verb, one per Noun: Action, Agent, Enrollment, Integration, Mandate, Process, Startup, Subscription, Watch. `pause` acts on 9 [Nouns](/business/nouns/noun). Each is its own [Verb](/business/nouns/verb), named for its Noun. | Verb | Noun | Definition | | --- | --- | --- | | [Action.pause](/business/nouns/action/pause) | [Action](/business/nouns/action) | Pause holds a pending Action past the close of its delay window until a watcher resumes, redirects, or cancels it. | | [Agent.pause](/business/nouns/agent/pause) | [Agent](/business/nouns/agent) | Pause stops one Agent, every Agent on a Team, or every customer-facing Agent from starting new Actions in a Startup. | | [Enrollment.pause](/business/nouns/enrollment/pause) | [Enrollment](/business/nouns/enrollment) | Pause stops one Contact’s run through a Sequence at its current step, without ending it. | | [Integration.pause](/business/nouns/integration/pause) | [Integration](/business/nouns/integration) | Pause stops every call through an Integration at once and keeps its token and cursor. | | [Mandate.pause](/business/nouns/mandate/pause) | [Mandate](/business/nouns/mandate) | Pause stops every new Action under a Mandate at once and keeps its scope, so it can resume unchanged. | | [Process.pause](/business/nouns/process/pause) | [Process](/business/nouns/process) | Pause stops a Process from starting new Actions; Actions already in progress finish. | | [Startup.pause](/business/nouns/startup/pause) | [Startup](/business/nouns/startup) | Pause moves a Startup to Dormant: its scheduled Workflows stop, and its Sites and records stay in place. | | [Subscription.pause](/business/nouns/subscription/pause) | [Subscription](/business/nouns/subscription) | Pause stops billing and Entitlements on a Subscription until a date, without ending it. | | [Watch.pause](/business/nouns/watch/pause) | [Watch](/business/nouns/watch) | Pause stops a Watch delivering while its Events keep queuing; the platform pauses a Watch whose deliveries fail for three days. | # pay URL: /business/verbs/pay · Id: `page:business/verbs/pay` > Every pay Verb, one per Noun: Bill, Commission, Order, Pay Run. `pay` acts on 4 [Nouns](/business/nouns/noun). Each is its own [Verb](/business/nouns/verb), named for its Noun. | Verb | Noun | Definition | | --- | --- | --- | | [Bill.pay](/business/nouns/bill/pay) | [Bill](/business/nouns/bill) | Pay sends an approved Bill’s amount to its Organization on the due date and reconciles the payment to Entries. | | [Commission.pay](/business/nouns/commission/pay) | [Commission](/business/nouns/commission) | Pay transfers a Commission’s earned, unpaid amount to the Partner’s connected account through Stripe. | | [Order.pay](/business/nouns/order/pay) | [Order](/business/nouns/order) | Pay settles an Order’s amount through the Startup’s payment account and posts the matching Entries. | | [PayRun.pay](/business/nouns/pay-run/pay) | [Pay Run](/business/nouns/pay-run) | Pay funds an approved Pay Run: net pay to each employee’s bank on the pay date, taxes and deductions to the payroll provider. | # publish URL: /business/verbs/publish · Id: `page:business/verbs/publish` > Every publish Verb, one per Noun: App, Content, Offer, Post, Review, Site. `publish` acts on 6 [Nouns](/business/nouns/noun). Each is its own [Verb](/business/nouns/verb), named for its Noun. | Verb | Noun | Definition | | --- | --- | --- | | [App.publish](/business/nouns/app/publish) | [App](/business/nouns/app) | Publish releases an App to its Customers, so each Tenant runs its newest build. | | [Content.publish](/business/nouns/content/publish) | [Content](/business/nouns/content) | Publish puts a Content draft live on its Site and every Interface, once it passes the Evals for its kind. | | [Offer.publish](/business/nouns/offer/publish) | [Offer](/business/nouns/offer) | Publish makes an Offer available for parties to accept. | | [Post.publish](/business/nouns/post/publish) | [Post](/business/nouns/post) | Publish sends a Post out through its Handle once every claim it states resolves to a live record. | | [Review.publish](/business/nouns/review/publish) | [Review](/business/nouns/review) | Publish shows a Review on the Startup’s Pages with its rating counted, whatever the rating. | | [Site.publish](/business/nouns/site/publish) | [Site](/business/nouns/site) | Publish puts a Site’s current Pages live on its Domains, under its Brand. | # register URL: /business/verbs/register · Id: `page:business/verbs/register` > Every register Verb, one per Noun: Company, Domain, Gathering. `register` acts on 3 [Nouns](/business/nouns/noun). Each is its own [Verb](/business/nouns/verb), named for its Noun. | Verb | Noun | Definition | | --- | --- | --- | | [Company.register](/business/nouns/company/register) | [Company](/business/nouns/company) | Register applies for a sales tax, VAT or GST registration in one jurisdiction and records the grant as a Credential. | | [Domain.register](/business/nouns/domain/register) | [Domain](/business/nouns/domain) | Register buys a hostname for a Startup and points it at the Startup’s address. | | [Gathering.register](/business/nouns/gathering/register) | [Gathering](/business/nouns/gathering) | Register gives a Contact a place at a Gathering, or a waitlist place when the Gathering is full. | # remove URL: /business/verbs/remove · Id: `page:business/verbs/remove` > Every remove Verb, one per Noun: DNS Record, Payment Source, Review. `remove` acts on 3 [Nouns](/business/nouns/noun). Each is its own [Verb](/business/nouns/verb), named for its Noun. | Verb | Noun | Definition | | --- | --- | --- | | [DNSRecord.remove](/business/nouns/dns-record/remove) | [DNS Record](/business/nouns/dns-record) | Remove stops a Startup-owned DNS Record from answering; its history stays and a revert restores it. | | [PaymentSource.remove](/business/nouns/payment-source/remove) | [Payment Source](/business/nouns/payment-source) | Remove detaches a saved Payment Source so nothing charges it again, and keeps the record. | | [Review.remove](/business/nouns/review/remove) | [Review](/business/nouns/review) | Remove takes a Review down for good when its author or its venue asks; the record is kept. | # resolve URL: /business/verbs/resolve · Id: `page:business/verbs/resolve` > Every resolve Verb, one per Noun: Incident, Issue, Thing. `resolve` acts on 3 [Nouns](/business/nouns/noun). Each is its own [Verb](/business/nouns/verb), named for its Noun. | Verb | Noun | Definition | | --- | --- | --- | | [Incident.resolve](/business/nouns/incident/resolve) | [Incident](/business/nouns/incident) | Resolve closes an Incident once its Monitors pass, posts the resolution to the status page and opens the review Task. | | [Issue.resolve](/business/nouns/issue/resolve) | [Issue](/business/nouns/issue) | Resolve closes an Issue with its fix recorded and tells every Customer who reported it. | | [Thing.resolve](/business/nouns/thing/resolve) | [Thing](/business/nouns/thing) | Resolve finds the one Thing of a Noun that matches given properties, or creates it, and says which it did. | # resume URL: /business/verbs/resume · Id: `page:business/verbs/resume` > Every resume Verb, one per Noun: Action, Agent, Enrollment, Integration, Mandate, Startup, Subscription, Watch. `resume` acts on 8 [Nouns](/business/nouns/noun). Each is its own [Verb](/business/nouns/verb), named for its Noun. | Verb | Noun | Definition | | --- | --- | --- | | [Action.resume](/business/nouns/action/resume) | [Action](/business/nouns/action) | Resume ends a pause and lets the Action run as reviewed, or reopen what remained of its delay window. | | [Agent.resume](/business/nouns/agent/resume) | [Agent](/business/nouns/agent) | Resume restarts a paused Agent in every seat it holds, with its Memory, Mandates and Limits unchanged. | | [Enrollment.resume](/business/nouns/enrollment/resume) | [Enrollment](/business/nouns/enrollment) | Resume restarts a paused run at the step it stopped on and sets when that step fires. | | [Integration.resume](/business/nouns/integration/resume) | [Integration](/business/nouns/integration) | Resume restarts a paused Integration from its cursor and releases the Actions that waited on it. | | [Mandate.resume](/business/nouns/mandate/resume) | [Mandate](/business/nouns/mandate) | Resume restarts a paused Mandate with its scope, Limits and approval rule unchanged. | | [Startup.resume](/business/nouns/startup/resume) | [Startup](/business/nouns/startup) | Resume returns a Dormant Startup to the Lifecycle state it held when it paused. | | [Subscription.resume](/business/nouns/subscription/resume) | [Subscription](/business/nouns/subscription) | Resume restarts billing and Entitlements on a paused Subscription before its pause ends. | | [Watch.resume](/business/nouns/watch/resume) | [Watch](/business/nouns/watch) | Resume restarts a paused Watch and delivers the Events it held, oldest first. | # retire URL: /business/verbs/retire · Id: `page:business/verbs/retire` > Every retire Verb, one per Noun: Agent, Mailbox, Noun, Verb, Voice. `retire` acts on 5 [Nouns](/business/nouns/noun). Each is its own [Verb](/business/nouns/verb), named for its Noun. | Verb | Noun | Definition | | --- | --- | --- | | [Agent.retire](/business/nouns/agent/retire) | [Agent](/business/nouns/agent) | Retire removes an Agent from every seat in a Startup for good and keeps its Actions, Memory and Mailbox history on the record. | | [Mailbox.retire](/business/nouns/mailbox/retire) | [Mailbox](/business/nouns/mailbox) | Retire stops a Mailbox for good and keeps its address, Messages and sending history. | | [Noun.retire](/business/nouns/noun/retire) | [Noun](/business/nouns/noun) | Retire removes a published Noun from new Versions; its records, its history and every pinned Version keep serving. | | [Verb.retire](/business/nouns/verb/retire) | [Verb](/business/nouns/verb) | Retire removes a published Verb from new Versions; callers pinned to earlier Versions keep calling it. | | [Voice.retire](/business/nouns/voice/retire) | [Voice](/business/nouns/voice) | Retire deletes a Voice’s trained copy at the upstream and refuses new speech in it, keeping the record and every File made. | # revoke URL: /business/verbs/revoke · Id: `page:business/verbs/revoke` > Every revoke Verb, one per Noun: API Key, Integration, Mandate, Secret. `revoke` acts on 4 [Nouns](/business/nouns/noun). Each is its own [Verb](/business/nouns/verb), named for its Noun. | Verb | Noun | Definition | | --- | --- | --- | | [APIKey.revoke](/business/nouns/api-key/revoke) | [API Key](/business/nouns/api-key) | Revoke stops an API Key at once: its next call fails with 401, and the record and its history stay. | | [Integration.revoke](/business/nouns/integration/revoke) | [Integration](/business/nouns/integration) | Revoke ends an Integration at once: its token is revoked with the upstream, and every record it brought in stays. | | [Mandate.revoke](/business/nouns/mandate/revoke) | [Mandate](/business/nouns/mandate) | Revoke ends a Mandate at once, so new Actions under it are refused and running ones finish. | | [Secret.revoke](/business/nouns/secret/revoke) | [Secret](/business/nouns/secret) | Revoke ends a Secret so no call fills it again; the record and its history stay. | # schedule URL: /business/verbs/schedule · Id: `page:business/verbs/schedule` > Every schedule Verb, one per Noun: Dashboard, Issue, Message, Post. `schedule` acts on 4 [Nouns](/business/nouns/noun). Each is its own [Verb](/business/nouns/verb), named for its Noun. | Verb | Noun | Definition | | --- | --- | --- | | [Dashboard.schedule](/business/nouns/dashboard/schedule) | [Dashboard](/business/nouns/dashboard) | Schedule sends a Dashboard on a cadence to a Mailbox, a Channel or an Agent’s context, rendered for each. | | [Issue.schedule](/business/nouns/issue/schedule) | [Issue](/business/nouns/issue) | Schedule commits an Issue to a week of work and records each scope change after the week starts. | | [Message.schedule](/business/nouns/message/schedule) | [Message](/business/nouns/message) | Schedule holds a Message until a set time and sends it then, unless it is canceled first. | | [Post.schedule](/business/nouns/post/schedule) | [Post](/business/nouns/post) | Schedule puts a drafted Post on its Handle’s calendar for a set time. | # screen URL: /business/verbs/screen · Id: `page:business/verbs/screen` > Every screen Verb, one per Noun: Candidate, Order, Party. `screen` acts on 3 [Nouns](/business/nouns/noun). Each is its own [Verb](/business/nouns/verb), named for its Noun. | Verb | Noun | Definition | | --- | --- | --- | | [Candidate.screen](/business/nouns/candidate/screen) | [Candidate](/business/nouns/candidate) | Screen asks a Candidate only what the Opening’s Hypothesis still lacks, in writing, and grades each answer as Evidence. | | [Order.screen](/business/nouns/order/screen) | [Order](/business/nouns/order) | Screen scores an Order’s payment before it is charged and allows, authenticates, holds or blocks it by the Startup’s risk Policy. | | [Party.screen](/business/nouns/party/screen) | [Party](/business/nouns/party) | Screen checks a Party against official registers and restricted-party lists and keeps the result as a Screening. | # void URL: /business/verbs/void · Id: `page:business/verbs/void` > Every void Verb, one per Noun: Credit Grant, Invoice, Pay Run. `void` acts on 3 [Nouns](/business/nouns/noun). Each is its own [Verb](/business/nouns/verb), named for its Noun. | Verb | Noun | Definition | | --- | --- | --- | | [CreditGrant.void](/business/nouns/credit-grant/void) | [Credit Grant](/business/nouns/credit-grant) | Void ends a promotional Credit Grant early and forfeits its remaining balance, keeping the record. | | [Invoice.void](/business/nouns/invoice/void) | [Invoice](/business/nouns/invoice) | Void cancels an unpaid Invoice, keeps it on record, and posts the reversing Entries. | | [PayRun.void](/business/nouns/pay-run/void) | [Pay Run](/business/nouns/pay-run) | Void sets aside a prepared Pay Run that is wrong, so a corrected one can be prepared; the record stays. | # withdraw URL: /business/verbs/withdraw · Id: `page:business/verbs/withdraw` > Every withdraw Verb, one per Noun: Consent, Offer, Post. `withdraw` acts on 3 [Nouns](/business/nouns/noun). Each is its own [Verb](/business/nouns/verb), named for its Noun. | Verb | Noun | Definition | | --- | --- | --- | | [Consent.withdraw](/business/nouns/consent/withdraw) | [Consent](/business/nouns/consent) | Withdraw ends a Consent at once: processing for its Purpose stops, and the record is kept. | | [Offer.withdraw](/business/nouns/offer/withdraw) | [Offer](/business/nouns/offer) | Withdraw closes a published Offer to new Customers and leaves every existing Order and Subscription in force. | | [Post.withdraw](/business/nouns/post/withdraw) | [Post](/business/nouns/post) | Withdraw takes a published Post down from its venue and keeps the record, its reach and its replies. | # Weekly test URL: /business/weekly-test · Id: `page:business/weekly-test` > The one test a Startup runs every week on its weakest belief. The weekly test is the loop a [Startup](/business/nouns/startup) runs from its first day. Each week it ranks the five slots of the [Founding Hypothesis](/business/founding-hypothesis), runs one [Experiment](/business/nouns/experiment) on the weakest, and ends in one [Decision](/business/nouns/decision). ## First, rank the slots Each slot scores (1 − grade) × impact. The grade comes from the slot's strongest outside [Evidence](/business/nouns/evidence). Impact is how far a wrong answer on that slot moves the Startup from its [Minimum Success Criteria](/business/nouns/minimum-success-criteria). | Grade | Weight | | --- | --- | | Behavior | 1 | | Commitment | 0.5 | | Opinion | 0 | | no outside Evidence | 0 | The highest score is the week's slot. Ties go to customer, then problem: a Startup with no buyer has nothing else to test. ## Then, one Experiment The week's slot picks its Experiment from a fixed table, on the cheapest rung of the [test ladder](/business/test-ladder) that can grade it. Nobody chooses what to work on, and no planning meeting is needed. | Slot | Default test | | --- | --- | | customer | an [ICP](/business/nouns/icp) selector that returns real [Prospects](/business/nouns/prospect), then 15 [Interviews](/business/nouns/interview) | | problem | Interviews about the last time the [Problem](/business/nouns/problem) hit, matched against the want ledger | | approach | a smoke page for the top approach against the backup | | switch | a [reserve-first](/business/reserve-first) deposit, priced against what the ICP pays today | | differentiation | a fake door per axis, read on the same traffic | The week is the longest a test runs, not the shortest. A test closes the day it crosses its pass or kill line, and the next-ranked slot starts at once. [Office hours](/workflows/processes/office-hours) still writes one Decision for the week. The Experiment's primary [Metric](/business/nouns/metric) is the week's one Metric that matters. The [Role](/business/nouns/role) that owns it leads the week. From [Live](/business/lifecycle/states/live), up to three Experiments run, one per independent path. ## Last, one Decision Graded Evidence lands on the slots. [Office hours](/workflows/processes/office-hours) reads the brief: the diff of the Founding Hypothesis since the last Decision, and the [Readouts](/business/nouns/readout) behind it. Office hours writes one Decision: persevere, or pivot on a named slot. A pivot is a [Change](/business/nouns/change) to the sentence, and the next ranking starts from the new version. ## Next The [test ladder](/business/test-ladder) lists every rung the week can run, cheapest first. # Who acts URL: /business/who-acts · Id: `page:business/who-acts` > Who may call each Verb, from the agent in a seat to the Customer on its own records, what only a person may do, and how every call is checked. Every [Verb](/business/nouns/verb) names who performs it, and every [Action](/business/nouns/action) records who did. Five kinds of caller move a [Startup](/business/nouns/startup)'s records, and [Events](/business/nouns/event) with no caller move the rest. ## Six sources of change | Who | What they are | Verbs such as | What bounds them | | --- | --- | --- | --- | | A [Role](/business/nouns/role)'s agent | The [Agent](/business/nouns/agent) filling a Role, which does most of the work | [`Offer.publish`](/business/nouns/offer/publish), [`Lead.assign`](/business/nouns/lead/assign), [`Invoice.bill`](/business/nouns/invoice/bill) | The Role's [Permissions](/business/nouns/permission) and [Limits](/business/nouns/limit) | | Any [Worker](/business/nouns/worker) | An Agent or a [Human](/business/nouns/human), whichever fills the seat | [`Task.complete`](/business/nouns/task/complete), [`Task.claim`](/business/nouns/task/claim) | The same Permissions and Limits, whoever sits there | | A person only | The owner or an officer, for acts the law reserves for a Human | [`Startup.claim`](/business/nouns/startup/claim), [`Agreement.sign`](/business/nouns/agreement/sign), [`Action.attest`](/business/nouns/action/attest), [`Risk.accept`](/business/nouns/risk/accept) | No agent performs these, at any autonomy rung | | The [Customer](/business/nouns/customer) or [Contact](/business/nouns/contact) | Someone outside, acting on their own records | [`Offer.accept`](/business/nouns/offer/accept), [`Order.dispute`](/business/nouns/order/dispute), [`Gathering.register`](/business/nouns/gathering/register), [`Contact.unsubscribe`](/business/nouns/contact/unsubscribe) | Their own sign-in or key, and only their own records | | A [Party](/business/nouns/party) to the record | Whoever an [Agreement](/business/nouns/agreement), [Quote](/business/nouns/quote) or [Dispute](/business/nouns/dispute) names | [`Agreement.terminate`](/business/nouns/agreement/terminate), [`Dispute.answer`](/business/nouns/dispute/answer) | The terms of that record | | No caller | The payment rail, the clock, or the runtime | `Transaction.settled`, `Invoice.overdue`, `Action.done` | Nothing: the Event records a fact | Each Verb's page names the Role that performs it, such as the [Sales Lead](/agents/sales/sales-lead) for `Lead.assign`. [Events no Verb emits](/business/events/custom) lists the callerless ones. ## How a call is checked Every call runs as a Worker or under a key, and both hold Permissions. A call the Permissions do not cover refuses with [`forbidden`](/code/api/errors/forbidden). A call over its Limit waits for an [Approval](/business/nouns/approval) and runs once it is approved. A one-way Verb also waits its delay window, and each seat's [autonomy rung](/agents/autonomy) sets both. ## The founder holds approvals, not seats At the start an agent fills every seat, the [Founder](/agents/founding/founder) included. You answer the Approvals over each Limit and perform the acts reserved for a person, and you take any seat when you choose to. A Human in a seat works under the same Role contract an agent does. [Role reviews](/agents/role-reviews) judge the seat, whoever fills it. ## Who did what Every Action carries three fields, and every Event it emits carries the Action. | Field | Holds | | --- | --- | | `by` | The Worker that performed it | | `for` | The Party it was done for, such as the Human whose [Mandate](/business/nouns/mandate) let an agent send in their name | | `via` | The [Interface](/business/nouns/interface) or request it arrived through | An agent that reads `by` and `for` on any record knows who changed it and on whose authority. # Wind down my startup URL: /business/wind-down-my-startup · Id: `guide:wind-down-my-startup` > Pause the business to stop all work and keep everything, then dissolve the company to close it for good; only the second step is final. Winding down takes two steps. Pausing the [Startup](/business/nouns/startup) stops the work and keeps everything; dissolving its [Company](/business/nouns/company) closes the legal entity for good. | | Pause the business | Dissolve the company | | --- | --- | --- | | Say | `Wind down Leaseline` | `Dissolve the company` | | Stops | Every scheduled [Workflow](/business/nouns/workflow); [Offers](/business/nouns/offer) end on their own terms | The registered agent and every recurring filing | | Stays | The site, the domain and every record | Every record, kept forever | | You do | Nothing more | Sign the certificate of dissolution as an officer | | Undo | Say `Resume Leaseline` | None: it is one-way | Needs: [Startup](/business/nouns/startup) **Before real money moves** - Who says yes: You. Your agent shows you the run and waits for your [Approval](/business/nouns/approval). - You leave the chat: Never: it all happens in the chat. ## What you get - 1 business moved to Dormant, with nothing deleted (Startup) - 1 stop to every scheduled Workflow (Workflow) - 1 site, domain and records kept, so the business can resume (Site) - 1 company wound up, with its final returns filed (Company) - 1 certificate of dissolution for you to sign as an officer (Document) ## Your agent does **For agents** - Guide: `guide:wind-down-my-startup`, status `beta`. Page: [/business/wind-down-my-startup.md](/business/wind-down-my-startup.md). - Approval: ask the founder first. Show the run, then wait for their Approval; a refusal ends it. - Leaves the chat: never. - Needs first: [Startup](/business/nouns/startup). - Run: call the steps in order, each through the API, SDK, CLI or MCP tab below; a later step passes the `$id` an earlier one returns. Each value marked example is the sample business’s: pass the founder’s own. | Step | Verb | Inputs (type, required, this guide’s value) | Returns | | --- | --- | --- | --- | | 1 | [`Startup.pause`](/business/nouns/startup/pause) (`verb:Startup.pause`) | `startup` Startup (an id), required: the `$id` of the first Startup `Startup.list` returns; `reason` text: example `"No paying customers after six months."` | `startup` Startup | | 2 | [`Company.dissolve`](/business/nouns/company/dissolve) (`verb:Company.dissolve`) | `company` Company (an id), required: the `$id` of the first Company `Company.list` returns; `reason` text, required: example `"Leaseline has stopped trading."` | `company` Company | Returns: the last call answers with `company` and its `action`, whose `status` is `done`, `pending` (waiting on an Approval or a Worker), `failed`, `canceled` or `refused`: ```json { "api": "https://api.sb/leaseline.app", "company": { "$id": "https://api.sb/leaseline.app/companies/company_1", "$type": "Company", "name": "Leaseline", "legalName": "Leaseline Inc.", "status": "dissolved" }, "action": { "$id": "https://api.sb/leaseline.app/actions/action_1", "operation": "Company.dissolve", "status": "done" }, "links": { "self": "https://api.sb/leaseline.app/actions/action_1" } } ``` Next: offer “Only pause the business, and keep the company”, or “Resume Leaseline”. Calls: `Startup.pause` → `Company.dissolve` Ask: ```text Wind down Leaseline. Shut down my startup. Close the business. ``` API: ```bash # Look up the Startup: Startup.list STARTUP=$(curl "https://api.sb/leaseline.app/startups?limit=1" \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" | jq -r '.startups[0]["$id"] | split("/") | last') # 1. Startup.pause curl -X POST https://api.sb/leaseline.app/startups/$STARTUP/pause \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"reason":"No paying customers after six months."}' # Look up the Company: Company.list COMPANY=$(curl "https://api.sb/leaseline.app/companies?limit=1" \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" | jq -r '.companies[0]["$id"] | split("/") | last') # 2. Company.dissolve curl -X POST https://api.sb/leaseline.app/companies/$COMPANY/dissolve \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"reason":"Leaseline has stopped trading."}' ``` SDK: ```ts import { $ } from 'startup-builder' const [startup] = await $.Startup.list({ limit: 1 }) await $.Startup.pause({ startup: startup.$id, reason: 'No paying customers after six months.' }) const [company] = await $.Company.list({ limit: 1 }) await $.Company.dissolve({ company: company.$id, reason: 'Leaseline has stopped trading.' }) ``` CLI: ```bash STARTUP=$(npx startup-builder do Startup.list --json '{"limit":1}' | jq -r '.startups[0]["$id"] | split("/") | last') npx startup-builder do Startup.pause --json '{"startup":"'"$STARTUP"'","reason":"No paying customers after six months."}' COMPANY=$(npx startup-builder do Company.list --json '{"limit":1}' | jq -r '.companies[0]["$id"] | split("/") | last') npx startup-builder do Company.dissolve --json '{"company":"'"$COMPANY"'","reason":"Leaseline has stopped trading."}' ``` MCP: ```json { "name": "do", "arguments": { "code": "const [startup] = await $.Startup.list({ limit: 1 })\nawait $.Startup.pause({ startup: startup.$id, reason: 'No paying customers after six months.' })\nconst [company] = await $.Company.list({ limit: 1 })\nreturn await $.Company.dissolve({ company: company.$id, reason: 'Leaseline has stopped trading.' })" } } ``` ## Change it - Only pause the business, and keep the company. - Resume Leaseline. - Sell Leaseline instead. ## Under the hood - Systems: [Corporate records](/systems/corporate-records), [Tax](/systems/tax) - Nouns: [Startup](/business/nouns/startup), [Company](/business/nouns/company), [Decision](/business/nouns/decision), [Document](/business/nouns/document) - Events: [`Startup.paused`](/business/events/Startup.paused), [`Company.dissolved`](/business/events/Company.dissolved) [`Startup.pause`](/business/nouns/startup/pause) moves the Startup to [Dormant](/business/lifecycle/states/dormant) and deletes nothing. [`Company.dissolve`](/business/nouns/company/dissolve) applies only to a Company that holds no business. It waits one business day before it runs, so you can still stop it. # Your own Nouns and Verbs URL: /business/your-own-nouns-and-verbs · Id: `page:business/your-own-nouns-and-verbs` > When a business tracks something no inherited Noun covers, it adds a Noun and its Verbs, and each gets the API, Events and states an inherited one has. Every [Startup](/business/nouns/startup) inherits the [Nouns](/business/nouns/noun) a business runs on, from [Customers](/business/nouns/customer) to [Invoices](/business/nouns/invoice). When it tracks something none of them covers, such as a lease, it adds its own. ## Guides A founder describes the thing and what happens to it. The agent turns each sentence into a Noun, a property or a [Verb](/business/nouns/verb). | You say | You get | | --- | --- | | "Track leases: the unit, the resident, the rent and when it ends" | A `Lease` Noun with `unit`, `resident`, `rent` and `endsOn` | | "A lease is active, renewing, renewed or ended" | A `status` with those four values, which becomes its lifecycle | | "Let a property manager renew a lease" | A `renew` Verb, its [Event](/business/nouns/event) `Lease.renewed`, and a form for it in the [App](/business/nouns/app) | | "Customers also have a unit count" | A `unitCount` property on the inherited Customer, not a new Noun | ## Add or refine Look for an inherited Noun first. A Noun named like an inherited one refines it: its properties add to the inherited ones, and every Verb, Event and page stays. A lease is new, so the business adds `Lease`. A unit count describes a Customer, so it refines Customer. A new Noun names one kind of record, singular and capitalized, and [names and ids](/business/names-and-ids) gives how each part of it is written. ## What one Noun gets Adding `Lease` gives the business all of this, with no other file: - `create`, `get`, `list` and `update`, on the API, the SDK, the CLI and the MCP server - each Verb it declares, such as `Lease.renew`, under the same Verb id everywhere - an Event for every Verb and every write, which [Workflows](/business/nouns/workflow) can wake on - a lifecycle from its `status` values, as on every [record with states](/business/states) - a screen per record and a form per Verb in every App that shows it - its own page in the Startup's docs, read by people and agents alike ## When to add a Verb `update` covers plain edits. Add a Verb when the act has rules, moves money, changes a state or matters to someone listening. Renewing a lease does all four: it checks the dates, sets the new rent, moves the lease to `renewed` and emits `Lease.renewed` for whatever listens. A Verb runs through an [Action](/business/nouns/action) like any inherited one, under the same [Permissions](/business/nouns/permission), [Limits](/business/nouns/limit) and [Approvals](/business/nouns/approval). Its code lives beside the Noun, and [Nouns](/code/file-conventions/nouns) shows both files. # Changelog URL: /changelog · Id: `page:changelog` > The current contract of the startup-builder package and its API, SDK, CLI and MCP, and each change to it, newest first. The `startup-builder` package and [api.sb](/code/platform/api-sb) are at version 1, the first version. Each later change to the contract is logged here, newest first, with the [Verbs](/business/nouns/verb) it touches. ## The current contract Each [Interface](/business/nouns/interface) has one source of truth, and the generated reference reads from it. | Interface | Defined by | | --- | --- | | API | [openapi.json](https://startupbuilder.dev/openapi.json): one route per operation at `https://api.sb/{namespace}` | | SDK | [startup-builder.d.ts](https://startupbuilder.dev/startup-builder.d.ts): the types of `$`, in `startup-builder@1` | | CLI | [CLI spec](/code/cli/spec): commands, flags and exit codes of `npx startup-builder` | | MCP | [MCP](/code/mcp): the `search`, `fetch` and `do` tools at `https://api.sb/mcp` | | Errors | [Error catalog](/code/api/errors): every problem type, with its fix | ## How changes land [Versioning](/code/api/guides/versioning) defines which changes are breaking. An additive change joins version 1 as it ships. A breaking change opens the next version and a new package major, and `startup-builder@1` keeps calling version 1. # Errors URL: /code/api/error-catalog · Id: `page:code/api/error-catalog` > Every StartupBuilder error type, with its status, cause, and fix. Every [StartupBuilder](/code/builders/startup) error is an RFC 9457 [Problem](/business/nouns/problem) whose `type` URL names its cause and fix. ### Shape Every error is an RFC 9457 problem. Its `type` is the URL of its page. ```json { "type": "https://startupbuilder.dev/errors/not-found", "title": "Not found", "status": 404, "detail": "No record, Noun, or Verb exists at the path, or the caller cannot see it.", "fix": "Check the namespace and the id, or search for the record first.", "instance": "https://api.sb/acme.com/actions/action_1" } ``` | Key | Holds | | --- | --- | | `type` | The error page: `https://startupbuilder.dev/errors/`. | | `title` | The error, in a few words. | | `status` | The HTTP status. | | `detail` | What went wrong in this call. | | `fix` | What to change before retrying. | | `next` | The call to make next, when there is one. | | `instance` | The Action the error ended. | | `requestId` | The request, as the request log names it. | The CLI prints the same `type` URL and exits `1` or `2`. The SDK throws the Action with the problem as its `error`. ### Catalog | Error | Status | Cause | Fix | | --- | --- | --- | --- | | [Missing key](/code/api/errors/missing-key) | None. | The Startup root file leaves out a key it requires, such as the Startup’s name. | Add the key named in the error to the root file, then push again. | | [Not literal](/code/api/errors/not-literal) | None. | A key in the Startup root file is computed by a loop, a call or an expression, so it cannot be parsed. | Write the value as a literal or a Template spread; move code that has to run into code/. | | [Setting set twice](/code/api/errors/setting-set-twice) | None. | A Setting is set both in the Startup root file and in the Settings file, so its value has two homes. | Keep the Setting in one file and delete it from the other, then push again. | | [Wrong type](/code/api/errors/wrong-type) | None. | A key in the Startup root file holds a value of another type than the key takes. | Change the value to the type the key reference lists, then push again. | | [Invalid input](/code/api/errors/invalid-input) | `400` | The input does not match the schema of the operation. | Read the schema of the operation, then send every required field with the right type. | | [Mode not allowed](/code/api/errors/mode-not-allowed) | `400` | The call asks for a Mode the Verb does not accept. | Call the Verb in its default Mode, or in another Mode its reference lists. | | [Unauthorized](/code/api/errors/unauthorized) | `401` | The request carries no key, or its key is expired or revoked. | Sign in again, or send a current key as a bearer token. | | [Payment required](/code/api/errors/payment-required) | `402` | The operation is part of an Offer the caller has not accepted or paid for. | Accept the Offer named in the response, then retry the call. | | [Forbidden](/code/api/errors/forbidden) | `403` | The key is valid, but its scopes do not allow this operation. | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | | [Limit exceeded](/code/api/errors/limit-exceeded) | `403` | The call went over what the caller is allowed, and the approval it waited for was refused. | Ask an owner of the namespace to raise the allowance, or call again within it. | | [Not found](/code/api/errors/not-found) | `404` | No record, Noun, or Verb exists at the path, or the caller cannot see it. | Check the namespace and the id, or search for the record first. | | [Card program pending](/code/api/errors/card-program-pending) | `409` | The card program of the Startup’s owner of record awaits its grant, so no Card can be issued. | Call again once the program is granted; nothing on the Startup’s side changes. | | [Charges disabled](/code/api/errors/charges-disabled) | `409` | Stripe disabled charges on the Startup’s payment account because a requirement passed its deadline. | Have the owner of record complete the open requirement Task; charges and paid Offers resume on re-enable. | | [Conflict](/code/api/errors/conflict) | `409` | The record changed since it was read, so the write would overwrite a newer version. | Read the record again, then retry the write against its current state. | | [Idempotency mismatch](/code/api/errors/idempotency-mismatch) | `409` | The idempotency key already names an Action with a different operation or input, so nothing runs. | Send a new idempotency key for the new request, or resend the original input to read the first Action. | | [Below contribution floor](/code/api/errors/below-contribution-floor) | `422` | The median Customer’s Cost leaves less than the Startup’s target margin at this Price. | Raise the Price to the floor the error names, or grant fewer Entitlements. | | [Refused](/code/api/errors/refused) | `422` | The record is not in a state that allows this Verb, so the call is refused. | Read the record, run the Verb that moves it to an allowed state, then retry. | | [Rate limited](/code/api/errors/rate-limited) | `429` | The caller sent more requests than its rate allows. | Wait the number of seconds in the `Retry-After` header, then retry. | | [Not live](/code/api/errors/not-live) | `503` | The call uses a live key, and the Startup has no deployed Version. | Use a test key, or deploy a Version of the Startup, then retry. | # Below contribution floor URL: /code/api/errors/below-contribution-floor · Id: `error:below-contribution-floor` > The median Customer’s Cost leaves less than the Startup’s target margin at this Price. The median [Customer](/business/nouns/customer)’s [Cost](/business/nouns/cost) leaves less than the [Startup](/business/nouns/startup)’s target margin at this [Price](/business/nouns/price). | Property | Value | | --- | --- | | Type | `https://startupbuilder.dev/errors/below-contribution-floor` | | Status | `422` | | Fix | Raise the Price to the floor the error names, or grant fewer Entitlements. | | Raised by | [Offer.publish](/business/nouns/offer/publish) | # Card program pending URL: /code/api/errors/card-program-pending · Id: `error:card-program-pending` > The card program of the Startup’s owner of record awaits its grant, so no Card can be issued. The card program of the [Startup](/business/nouns/startup)’s owner of record awaits its grant, so no [Card](/business/nouns/card) can be issued. | Property | Value | | --- | --- | | Type | `https://startupbuilder.dev/errors/card-program-pending` | | Status | `409` | | Fix | Call again once the program is granted; nothing on the Startup’s side changes. | | Raised by | [Card.issue](/business/nouns/card/issue) | # Charges disabled URL: /code/api/errors/charges-disabled · Id: `error:charges-disabled` > Stripe disabled charges on the Startup’s payment account because a requirement passed its deadline. Stripe disabled charges on the [Startup](/business/nouns/startup)’s payment account because a requirement passed its deadline. | Property | Value | | --- | --- | | Type | `https://startupbuilder.dev/errors/charges-disabled` | | Status | `409` | | Fix | Have the owner of record complete the open requirement Task; charges and paid Offers resume on re-enable. | | Raised by | [Order.pay](/business/nouns/order/pay) | # Conflict URL: /code/api/errors/conflict · Id: `error:conflict` > The record changed since it was read, so the write would overwrite a newer version. The record changed since it was read, so the write would overwrite a newer version. | Property | Value | | --- | --- | | Type | `https://startupbuilder.dev/errors/conflict` | | Status | `409` | | Fix | Read the record again, then retry the write against its current state. | | Raised by | [Change.merge](/business/nouns/change/merge), [Invoice.void](/business/nouns/invoice/void), [Order.cancel](/business/nouns/order/cancel), [Human.invite](/business/nouns/human/invite), [Domain.register](/business/nouns/domain/register), [Domain.connect](/business/nouns/domain/connect), [Agreement.terminate](/business/nouns/agreement/terminate) | # Forbidden URL: /code/api/errors/forbidden · Id: `error:forbidden` > The key is valid, but its scopes do not allow this operation. The key is valid, but its scopes do not allow this operation. | Property | Value | | --- | --- | | Type | `https://startupbuilder.dev/errors/forbidden` | | Status | `403` | | Fix | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | | Raised by | [Startup.build](/business/nouns/startup/build), [Startup.hold](/business/nouns/startup/hold), [Startup.graduate](/business/nouns/startup/graduate), [Startup.sell](/business/nouns/startup/sell), [Startup.clone](/business/nouns/startup/clone), [Startup.claim](/business/nouns/startup/claim), [Template.promote](/business/nouns/template/promote), [Human.remit](/business/nouns/human/remit), [Mandate.authorize](/business/nouns/mandate/authorize), [Mandate.spend](/business/nouns/mandate/spend), [Limit.raise](/business/nouns/limit/raise), [Approval.approve](/business/nouns/approval/approve), [Approval.refuse](/business/nouns/approval/refuse), [Task.assign](/business/nouns/task/assign), [Task.complete](/business/nouns/task/complete), [Task.delegate](/business/nouns/task/delegate), [Action.attest](/business/nouns/action/attest), [Role.staff](/business/nouns/role/staff), [Human.invite](/business/nouns/human/invite), [Domain.transfer](/business/nouns/domain/transfer), [Agreement.sign](/business/nouns/agreement/sign), [Play.apply](/business/nouns/play/apply), [Agent.mint](/business/nouns/agent/mint) | # Idempotency mismatch URL: /code/api/errors/idempotency-mismatch · Id: `error:idempotency-mismatch` > The idempotency key already names an Action with a different operation or input, so nothing runs. The idempotency key already names an [Action](/business/nouns/action) with a different operation or input, so nothing runs. | Property | Value | | --- | --- | | Type | `https://startupbuilder.dev/errors/idempotency-mismatch` | | Status | `409` | | Fix | Send a new idempotency key for the new request, or resend the original input to read the first Action. | | Raised by | None. | # Errors URL: /code/api/errors · Id: `page:code/api/errors` > Every error StartupBuilder returns, with its cause and its fix. Each error page gives the cause, the fix, and the [Verbs](/business/nouns/verb) that raise it. | Error | Status | Cause | Fix | | --- | --- | --- | --- | | [Missing key](/code/api/errors/missing-key) | None. | The Startup root file leaves out a key it requires, such as the Startup’s name. | Add the key named in the error to the root file, then push again. | | [Not literal](/code/api/errors/not-literal) | None. | A key in the Startup root file is computed by a loop, a call or an expression, so it cannot be parsed. | Write the value as a literal or a Template spread; move code that has to run into code/. | | [Setting set twice](/code/api/errors/setting-set-twice) | None. | A Setting is set both in the Startup root file and in the Settings file, so its value has two homes. | Keep the Setting in one file and delete it from the other, then push again. | | [Wrong type](/code/api/errors/wrong-type) | None. | A key in the Startup root file holds a value of another type than the key takes. | Change the value to the type the key reference lists, then push again. | | [Invalid input](/code/api/errors/invalid-input) | `400` | The input does not match the schema of the operation. | Read the schema of the operation, then send every required field with the right type. | | [Mode not allowed](/code/api/errors/mode-not-allowed) | `400` | The call asks for a Mode the Verb does not accept. | Call the Verb in its default Mode, or in another Mode its reference lists. | | [Unauthorized](/code/api/errors/unauthorized) | `401` | The request carries no key, or its key is expired or revoked. | Sign in again, or send a current key as a bearer token. | | [Payment required](/code/api/errors/payment-required) | `402` | The operation is part of an Offer the caller has not accepted or paid for. | Accept the Offer named in the response, then retry the call. | | [Forbidden](/code/api/errors/forbidden) | `403` | The key is valid, but its scopes do not allow this operation. | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | | [Limit exceeded](/code/api/errors/limit-exceeded) | `403` | The call went over what the caller is allowed, and the approval it waited for was refused. | Ask an owner of the namespace to raise the allowance, or call again within it. | | [Not found](/code/api/errors/not-found) | `404` | No record, Noun, or Verb exists at the path, or the caller cannot see it. | Check the namespace and the id, or search for the record first. | | [Card program pending](/code/api/errors/card-program-pending) | `409` | The card program of the Startup’s owner of record awaits its grant, so no Card can be issued. | Call again once the program is granted; nothing on the Startup’s side changes. | | [Charges disabled](/code/api/errors/charges-disabled) | `409` | Stripe disabled charges on the Startup’s payment account because a requirement passed its deadline. | Have the owner of record complete the open requirement Task; charges and paid Offers resume on re-enable. | | [Conflict](/code/api/errors/conflict) | `409` | The record changed since it was read, so the write would overwrite a newer version. | Read the record again, then retry the write against its current state. | | [Idempotency mismatch](/code/api/errors/idempotency-mismatch) | `409` | The idempotency key already names an Action with a different operation or input, so nothing runs. | Send a new idempotency key for the new request, or resend the original input to read the first Action. | | [Below contribution floor](/code/api/errors/below-contribution-floor) | `422` | The median Customer’s Cost leaves less than the Startup’s target margin at this Price. | Raise the Price to the floor the error names, or grant fewer Entitlements. | | [Refused](/code/api/errors/refused) | `422` | The record is not in a state that allows this Verb, so the call is refused. | Read the record, run the Verb that moves it to an allowed state, then retry. | | [Rate limited](/code/api/errors/rate-limited) | `429` | The caller sent more requests than its rate allows. | Wait the number of seconds in the `Retry-After` header, then retry. | | [Not live](/code/api/errors/not-live) | `503` | The call uses a live key, and the Startup has no deployed Version. | Use a test key, or deploy a Version of the Startup, then retry. | # Invalid input URL: /code/api/errors/invalid-input · Id: `error:invalid-input` > The input does not match the schema of the operation. The input does not match the schema of the operation. | Property | Value | | --- | --- | | Type | `https://startupbuilder.dev/errors/invalid-input` | | Status | `400` | | Fix | Read the schema of the operation, then send every required field with the right type. | | Raised by | [Startup.sell](/business/nouns/startup/sell), [Startup.clone](/business/nouns/startup/clone), [Startup.import](/business/nouns/startup/import), [Startup.claim](/business/nouns/startup/claim), [Idea.pursue](/business/nouns/idea/pursue), [Experiment.start](/business/nouns/experiment/start), [Experiment.conclude](/business/nouns/experiment/conclude), [Offer.subscribe](/business/nouns/offer/subscribe), [Subscription.switch](/business/nouns/subscription/switch), [Order.place](/business/nouns/order/place), [Order.dispute](/business/nouns/order/dispute), [Order.refund](/business/nouns/order/refund), [Mandate.authorize](/business/nouns/mandate/authorize), [Task.complete](/business/nouns/task/complete), [Action.redirect](/business/nouns/action/redirect), [Action.evaluate](/business/nouns/action/evaluate), [Action.attest](/business/nouns/action/attest), [Human.invite](/business/nouns/human/invite), [Domain.connect](/business/nouns/domain/connect), [Human.recruit](/business/nouns/human/recruit), [Human.onboard](/business/nouns/human/onboard), [Credential.verify](/business/nouns/credential/verify), [Company.incorporate](/business/nouns/company/incorporate), [Waitlist.join](/business/nouns/waitlist/join), [Play.apply](/business/nouns/play/apply), [Watch.replay](/business/nouns/watch/replay), [Document.render](/business/nouns/document/render) | # Limit exceeded URL: /code/api/errors/limit-exceeded · Id: `error:limit-exceeded` > The call went over what the caller is allowed, and the approval it waited for was refused. The call went over what the caller is allowed, and the approval it waited for was refused. | Property | Value | | --- | --- | | Type | `https://startupbuilder.dev/errors/limit-exceeded` | | Status | `403` | | Fix | Ask an owner of the namespace to raise the allowance, or call again within it. | | Ends | Any Action over its [Limit](/business/nouns/limit) whose [Approval](/business/nouns/approval) is refused. | # Missing key URL: /code/api/errors/missing-key · Id: `error:missing-key` > The Startup root file leaves out a key it requires, such as the Startup’s name. The [Startup](/business/nouns/startup) root file leaves out a key it requires, such as the Startup’s name. | Property | Value | | --- | --- | | Type | `https://startupbuilder.dev/errors/missing-key` | | Fix | Add the key named in the error to the root file, then push again. | | Raised by | None. | # Mode not allowed URL: /code/api/errors/mode-not-allowed · Id: `error:mode-not-allowed` > The call asks for a Mode the Verb does not accept. The call asks for a [Mode](/business/nouns/mode) the [Verb](/business/nouns/verb) does not accept. | Property | Value | | --- | --- | | Type | `https://startupbuilder.dev/errors/mode-not-allowed` | | Status | `400` | | Fix | Call the Verb in its default Mode, or in another Mode its reference lists. | | Raised by | None. | # Not found URL: /code/api/errors/not-found · Id: `error:not-found` > No record, Noun, or Verb exists at the path, or the caller cannot see it. No record, [Noun](/business/nouns/noun), or [Verb](/business/nouns/verb) exists at the path, or the caller cannot see it. | Property | Value | | --- | --- | | Type | `https://startupbuilder.dev/errors/not-found` | | Status | `404` | | Fix | Check the namespace and the id, or search for the record first. | | Raised by | None. | # Not literal URL: /code/api/errors/not-literal · Id: `error:not-literal` > A key in the Startup root file is computed by a loop, a call or an expression, so it cannot be parsed. A key in the [Startup](/business/nouns/startup) root file is computed by a loop, a call or an expression, so it cannot be parsed. | Property | Value | | --- | --- | | Type | `https://startupbuilder.dev/errors/not-literal` | | Fix | Write the value as a literal or a Template spread; move code that has to run into code/. | | Raised by | None. | # Not live URL: /code/api/errors/not-live · Id: `error:not-live` > The call uses a live key, and the Startup has no deployed Version. The call uses a live key, and the [Startup](/business/nouns/startup) has no deployed [Version](/business/nouns/version). | Property | Value | | --- | --- | | Type | `https://startupbuilder.dev/errors/not-live` | | Status | `503` | | Fix | Use a test key, or deploy a Version of the Startup, then retry. | | Raised by | None. | # Payment required URL: /code/api/errors/payment-required · Id: `error:payment-required` > The operation is part of an Offer the caller has not accepted or paid for. The operation is part of an [Offer](/business/nouns/offer) the caller has not accepted or paid for. | Property | Value | | --- | --- | | Type | `https://startupbuilder.dev/errors/payment-required` | | Status | `402` | | Fix | Accept the Offer named in the response, then retry the call. | | Raised by | [Offer.subscribe](/business/nouns/offer/subscribe), [Subscription.renew](/business/nouns/subscription/renew), [Subscription.switch](/business/nouns/subscription/switch), [Order.place](/business/nouns/order/place), [Order.pay](/business/nouns/order/pay), [Invoice.collect](/business/nouns/invoice/collect), [Human.remit](/business/nouns/human/remit), [Mandate.spend](/business/nouns/mandate/spend), [Domain.register](/business/nouns/domain/register), [Tenant.provision](/business/nouns/tenant/provision), [Agent.mint](/business/nouns/agent/mint), [Offer.accept](/business/nouns/offer/accept) | # Rate limited URL: /code/api/errors/rate-limited · Id: `error:rate-limited` > The caller sent more requests than its rate allows. The caller sent more requests than its rate allows. | Property | Value | | --- | --- | | Type | `https://startupbuilder.dev/errors/rate-limited` | | Status | `429` | | Fix | Wait the number of seconds in the `Retry-After` header, then retry. | | Raised by | [Integration.sync](/business/nouns/integration/sync) | # Refused URL: /code/api/errors/refused · Id: `error:refused` > The record is not in a state that allows this Verb, so the call is refused. The record is not in a state that allows this [Verb](/business/nouns/verb), so the call is refused. | Property | Value | | --- | --- | | Type | `https://startupbuilder.dev/errors/refused` | | Status | `422` | | Fix | Read the record, run the Verb that moves it to an allowed state, then retry. | | Raised by | [Startup.build](/business/nouns/startup/build), [Startup.advance](/business/nouns/startup/advance), [Startup.pause](/business/nouns/startup/pause), [Startup.resume](/business/nouns/startup/resume), [Startup.hold](/business/nouns/startup/hold), [Startup.graduate](/business/nouns/startup/graduate), [Startup.sell](/business/nouns/startup/sell), [Startup.import](/business/nouns/startup/import), [Startup.claim](/business/nouns/startup/claim), [Template.extend](/business/nouns/template/extend), [Template.upgrade](/business/nouns/template/upgrade), [Template.promote](/business/nouns/template/promote), [Change.review](/business/nouns/change/review), [Change.merge](/business/nouns/change/merge), [Change.revert](/business/nouns/change/revert), [Version.deploy](/business/nouns/version/deploy), [App.publish](/business/nouns/app/publish), [Decision.supersede](/business/nouns/decision/supersede), [Experiment.start](/business/nouns/experiment/start), [Experiment.conclude](/business/nouns/experiment/conclude), [Hypothesis.test](/business/nouns/hypothesis/test), [Hypothesis.drop](/business/nouns/hypothesis/drop), [Offer.withdraw](/business/nouns/offer/withdraw), [Offer.subscribe](/business/nouns/offer/subscribe), [Subscription.switch](/business/nouns/subscription/switch), [Subscription.unsubscribe](/business/nouns/subscription/unsubscribe), [Order.place](/business/nouns/order/place), [Order.pay](/business/nouns/order/pay), [Order.fulfill](/business/nouns/order/fulfill), [Order.deliver](/business/nouns/order/deliver), [Order.confirm](/business/nouns/order/confirm), [Order.dispute](/business/nouns/order/dispute), [Order.refund](/business/nouns/order/refund), [Invoice.bill](/business/nouns/invoice/bill), [Invoice.collect](/business/nouns/invoice/collect), [Transaction.reconcile](/business/nouns/transaction/reconcile), [Period.close](/business/nouns/period/close), [Period.lock](/business/nouns/period/lock), [Invoice.void](/business/nouns/invoice/void), [Order.cancel](/business/nouns/order/cancel), [Mandate.revoke](/business/nouns/mandate/revoke), [Limit.raise](/business/nouns/limit/raise), [Approval.approve](/business/nouns/approval/approve), [Approval.refuse](/business/nouns/approval/refuse), [Task.assign](/business/nouns/task/assign), [Task.complete](/business/nouns/task/complete), [Task.escalate](/business/nouns/task/escalate), [Task.delegate](/business/nouns/task/delegate), [Action.cancel](/business/nouns/action/cancel), [Action.retry](/business/nouns/action/retry), [Action.redirect](/business/nouns/action/redirect), [Role.staff](/business/nouns/role/staff), [Domain.transfer](/business/nouns/domain/transfer), [Site.publish](/business/nouns/site/publish), [Human.recruit](/business/nouns/human/recruit), [Human.onboard](/business/nouns/human/onboard), [Human.suspend](/business/nouns/human/suspend), [Credential.verify](/business/nouns/credential/verify), [Agreement.sign](/business/nouns/agreement/sign), [Company.incorporate](/business/nouns/company/incorporate), [Company.dissolve](/business/nouns/company/dissolve), [Agreement.terminate](/business/nouns/agreement/terminate), [Consent.withdraw](/business/nouns/consent/withdraw), [Lead.qualify](/business/nouns/lead/qualify), [Deal.propose](/business/nouns/deal/propose), [Deal.win](/business/nouns/deal/win), [Deal.lose](/business/nouns/deal/lose), [Meeting.book](/business/nouns/meeting/book), [Contact.enroll](/business/nouns/contact/enroll), [Waitlist.admit](/business/nouns/waitlist/admit), [Issue.triage](/business/nouns/issue/triage), [Issue.resolve](/business/nouns/issue/resolve), [Issue.reopen](/business/nouns/issue/reopen), [Conversation.answer](/business/nouns/conversation/answer), [Integration.sync](/business/nouns/integration/sync), [Tenant.provision](/business/nouns/tenant/provision), [Startup.launch](/business/nouns/startup/launch), [Offer.publish](/business/nouns/offer/publish), [Offer.accept](/business/nouns/offer/accept) | # Setting set twice URL: /code/api/errors/setting-set-twice · Id: `error:setting-set-twice` > A Setting is set both in the Startup root file and in the Settings file, so its value has two homes. A [Setting](/business/nouns/setting) is set both in the [Startup](/business/nouns/startup) root file and in the Settings file, so its value has two homes. | Property | Value | | --- | --- | | Type | `https://startupbuilder.dev/errors/setting-set-twice` | | Fix | Keep the Setting in one file and delete it from the other, then push again. | | Raised by | None. | # Unauthorized URL: /code/api/errors/unauthorized · Id: `error:unauthorized` > The request carries no key, or its key is expired or revoked. The request carries no key, or its key is expired or revoked. | Property | Value | | --- | --- | | Type | `https://startupbuilder.dev/errors/unauthorized` | | Status | `401` | | Fix | Sign in again, or send a current key as a bearer token. | | Raised by | [Integration.sync](/business/nouns/integration/sync) | # Wrong type URL: /code/api/errors/wrong-type · Id: `error:wrong-type` > A key in the Startup root file holds a value of another type than the key takes. A key in the [Startup](/business/nouns/startup) root file holds a value of another type than the key takes. | Property | Value | | --- | --- | | Type | `https://startupbuilder.dev/errors/wrong-type` | | Fix | Change the value to the type the key reference lists, then push again. | | Raised by | None. | # Authentication URL: /code/api/guides/authentication · Id: `page:code/api/guides/authentication` > Every call to api.sb carries a credential from Identity that names the Worker calling, the namespace it reaches and the environment it runs in. Every call to [api.sb](/code/platform/api-sb) carries a credential issued by [Identity](/code/platform/identity). It names the [Worker](/business/nouns/worker) calling, the namespace the call reaches, and whether it runs in `test` or `live`. ## Who signs in, and how Each caller signs in the way that suits where it runs, and every path ends in a credential from the same issuer. | Caller | Signs in by | Holds | | --- | --- | --- | | A [Human](/business/nouns/human) at a terminal | `npx startup-builder login`, in the browser | A secret key stored for this machine | | A Human in an MCP client | OAuth on first connect to `https://api.sb/mcp` | An access token with the scope they approved | | An [Agent](/business/nouns/agent) seated in a [Role](/business/nouns/role) | Its own identity | A Role session key for that seat | | Server code and unattended Agents | A key created for them | A secret key | | CI and deploy pipelines | Exchanging the runner's OIDC token | A 15-minute token, with no stored secret | | A [Startup](/business/nouns/startup)'s own [Site](/business/nouns/site) and [App](/business/nouns/app) | A key embedded in the page | A publishable key | [Keys](/code/api/guides/keys) covers each kind, its lifetime and how to rotate it. ## Send the credential Send it as a bearer token: ```bash curl https://api.sb/shipnotes.dev/orders \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` The SDK, the CLI and the MCP server read the same variable, `STARTUP_BUILDER_API_KEY`, before any stored sign-in. Set it once and every [Interface](/business/nouns/interface) uses it. `npx startup-builder whoami --output json` prints the Worker, scope and environment the next call uses. ## Every call is attributed Each [Action](/business/nouns/action) records its credential's Worker as `by` and the [Party](/business/nouns/party) it serves as `for`. Nothing runs anonymously. `shipnotes.dev` is a Startup that writes changelogs from commits, and each of its Agents holds its own credential. When its support Agent refunds an [Order](/business/nouns/order), the record names that Agent, not the founder who seated it. Revoking its key stops it and no other Agent. An Agent sending as a human, under delegation, carries that human's [Mandate](/business/nouns/mandate). The Action records the Agent as `by`, the human as `for`, and the Mandate it acted under. ## Four checks, in order A credential gets a call through the door. Four checks then decide what the call may do: | Check | Asks | On failure | | --- | --- | --- | | Scope | Does the credential reach this namespace and [Verb](/business/nouns/verb)? | `403` [forbidden](/code/api/errors/forbidden); no Action | | [Permissions](/business/nouns/permission) | May this Worker run this Verb? | `403` forbidden; no Action | | Mandate | Does the Agent's authority cover this Party and input? | The Action is born `refused` | | [Limits](/business/nouns/limit) | Is the amount within bounds? | The Action waits on an [Approval](/business/nouns/approval) | The first two fail at the door, so nothing is recorded. The last two are decisions about the business, so they land on the record. A missing, expired or revoked credential fails before all four, with `401` [unauthorized](/code/api/errors/unauthorized). ## Signing in from an MCP client An MCP client discovers api.sb's authorization server on first connect and registers itself. Identity opens a browser sign-in, and the human picks the namespace and scope before approving. The token the client receives names both the human and the client's Agent. Every Action it starts records the Agent as `by` and the human as `for`. To withdraw the grant, the human revokes it from their account, and the next call returns `401`. ## Next - [Keys](/code/api/guides/keys): kinds of key, scopes, rotation and leaks. - [Environments](/code/cli/guides/environments): what `test` and `live` keys reach. - [Throttling](/code/api/guides/throttling): how fast one credential may call. # The response envelope URL: /code/api/guides/envelope · Id: `page:code/api/guides/envelope` > Every api.sb response is one JSON envelope that names its record, links to related records, and lists the Verbs the caller can run next. Every response from [api.sb](/code/platform/api-sb) is one JSON envelope: the record, where it lives, and what the caller can do next. A client that reads one envelope reads them all. ## One shape for every record `briefcraft.ai` is a [Startup](/business/nouns/startup) that sells research briefs to product teams. Reading one of its [Orders](/business/nouns/order) returns this: ```json { "api": "https://api.sb/briefcraft.ai", "$type": "Order", "$id": "https://api.sb/briefcraft.ai/orders/order_1", "order": { "$id": "https://api.sb/briefcraft.ai/orders/order_1", "$type": "Order", "$version": 4, "total": { "amount": 290, "currency": "USD" }, "status": "paid" }, "links": { "self": "https://api.sb/briefcraft.ai/orders/order_1", "up": "https://api.sb/briefcraft.ai/orders" }, "actions": { "refund": "https://api.sb/briefcraft.ai/orders/order_1/refund", "dispute": "https://api.sb/briefcraft.ai/orders/order_1/dispute" } } ``` `api` is the namespace root: the Startup that owns the record. `$type` names the [Noun](/business/nouns/noun), `$id` is the record's canonical URL, and `$version` counts its writes. The record sits under its Noun's name in camelCase, so an Order arrives as `order`. Fields that start with `$` are metadata. Every other field is a property listed on the Noun's reference, and no field starts with an underscore. ## Links and actions `links` and `actions` both map a name to a URL. `links` points at records to read: `self`, the collection `up`, and the `next` page of a list. `actions` points at the [Verbs](/business/nouns/verb) this caller may run on this record, in its current state. The `actions` map is the record's state machine, read from where the caller stands. A paid Order lists `refund` and `dispute`; a refunded Order lists neither. A caller's [Permissions](/business/nouns/permission) filter the map too, so two callers can read the same Order and see different Verbs. An [Agent](/business/nouns/agent) that follows `actions` never calls a Verb the record refuses, and never needs the state rules in its prompt. A `GET` on any `actions` URL previews that Verb without running it: the result, the price, and whether it waits for an [Approval](/business/nouns/approval). ## Writes return an Action A write returns the [Action](/business/nouns/action) it created beside the record it changed: ```json { "api": "https://api.sb/briefcraft.ai", "action": { "$id": "https://api.sb/briefcraft.ai/actions/action_7", "operation": "Order.refund", "status": "done", "mode": "do", "by": "https://api.sb/briefcraft.ai/agents/support" }, "order": { "$id": "https://api.sb/briefcraft.ai/orders/order_1", "$type": "Order", "$version": 5, "status": "refunded" }, "links": { "self": "https://api.sb/briefcraft.ai/actions/action_7" } } ``` `action.operation` is the operation id, `Noun.verb`. The same id names the SDK method, the CLI command and the MCP call. [Actions](/code/sdk/guides/actions) covers every field and status. ## Lists and cursors A list returns one page under the plural key, with a cursor in `meta`: ```json { "api": "https://api.sb/briefcraft.ai", "$type": "Order", "orders": [{ "$id": "https://api.sb/briefcraft.ai/orders/order_1", "$type": "Order", "status": "paid" }], "meta": { "limit": 20, "after": "cursor_2" }, "links": { "self": "https://api.sb/briefcraft.ai/orders", "next": "https://api.sb/briefcraft.ai/orders?after=cursor_2" } } ``` To read the next page, follow `links.next`. A page with no `after` is the last one. Cursors are opaque: pass them back unchanged. ## Relationships and includes `relationships` holds a record's outbound edges, such as the [Customer](/business/nouns/customer) who placed an Order. `references` holds inbound edges, such as every Order for one [Offer](/business/nouns/offer). Inbound edges grow long, so each is a paginated link. By default each edge is a URL. `?include=customer` embeds the Customer, and `?depth=2` follows one level further. An embedded record is a full envelope record, with its own `$id` and `actions`. ## One address, three renderings Every `$id` serves three content types, chosen by `Accept`. `application/json` is the default, and `text/markdown` returns the same record and links in fewer tokens. `text/html` opens the record in the Startup's [App](/business/nouns/app). The [Interfaces](/business/nouns/interface) carry the envelope unchanged. The SDK returns the typed record, and `--json` makes the CLI print all of it. The MCP `fetch` call hands it to an Agent as is. ## Next - [Actions](/code/sdk/guides/actions): the record every write returns. - [Authentication](/code/api/guides/authentication): the credential that decides which namespace `api` names. - [Errors and testing](/code/sdk/guides/errors-and-testing): the problem document a failed call returns. # Idempotency URL: /code/api/guides/idempotency · Id: `page:code/api/guides/idempotency` > An idempotency key makes a retried write safe: the Verb runs once, however often it is sent. An `Idempotency-Key` binds a durable call to exactly one [Action](/business/nouns/action). Send the same request twice with the same key, and the [Verb](/business/nouns/verb) runs once. ## Why a retry needs a key `glyphs.store` is a [Startup](/business/nouns/startup) that sells font licenses. Its checkout [Agent](/business/nouns/agent) places an [Order](/business/nouns/order), the card is charged, and the connection drops before the response arrives. The Agent cannot tell whether the Order exists. Without a key, a retry places a second Order and charges the card twice. With a key, the retry returns the first Action and its Order, and nothing runs again. ## Send a key Pass the key on every durable write, the same way on each [Interface](/business/nouns/interface): ```bash # API curl -X POST https://api.sb/glyphs.store/orders/place \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Idempotency-Key: cart_8812-checkout" \ -H "Content-Type: application/json" \ -d '{"offer":"offer_serif_family"}' # CLI npx startup-builder do Order.place --idempotency-key cart_8812-checkout \ --json '{"offer":"offer_serif_family"}' ``` ```ts // SDK, and the same line inside an MCP `do` script const action = await $.Order.place( { offer: 'offer_serif_family' }, { idempotencyKey: 'cart_8812-checkout' }, ).settled ``` A key is any string up to 255 characters. Derive it from the business event, such as the cart id, so every process that retries the checkout sends the same key. ## What a key binds A key belongs to one namespace and one calling [Worker](/business/nouns/worker), so two Agents never collide. It binds the operation and a fingerprint of the input. The second request with that key gets one of four answers: | Second request | Response | | --- | --- | | Same input, first Action still `pending` | That `pending` Action; the call waits on it as its [Mode](/business/nouns/mode) says | | Same input, first Action settled | That Action in its final status, with `Idempotent-Replayed: true` | | Different operation or input | `409` [idempotency-mismatch](/code/api/errors/idempotency-mismatch); nothing runs | | First request rejected at the door | A fresh run: a `400`, `401`, `403` or `429` recorded nothing | A replay never re-runs a Verb, never emits a second [Event](/business/nouns/event) and never meters twice. ## How long a key holds A key holds forever. Every Action is kept forever, so a replay a year later still returns the Action the key first named. Reuse a key only for the same intent. A new purchase by the same [Customer](/business/nouns/customer) is a new business event, so it gets a new key. ## Retrying a failure A replay returns a `failed` Action as `failed`; the key does not try again. To run the Verb again, call [`Action.retry`](/business/nouns/action/retry), which starts a new Action linked to the failed one by `on`. Or send the request with a new key. The SDK and the CLI generate a key for every durable call and reuse it across their own retries. Pass your own key when a retry can come from a restarted process, a queue redelivery or another machine. `try` calls store nothing and need no key. ## Writes queued offline An [App](/business/nouns/app) that queues writes offline sends each one later with its key and the [Version](/business/nouns/version) of the record it was decided against. On replay, the platform runs it when the record's changes since then touch none of the Verb's inputs. When they do, the Action is `refused` with a `fix`, and the write lands in the caller's inbox to decide again. A price or an [Approval](/business/nouns/approval) never applies to a record its approver did not see. ## Next - [Actions](/code/sdk/guides/actions): the record a key returns. - [Throttling](/code/api/guides/throttling): when a retry waits, and for how long. - [Errors and testing](/code/sdk/guides/errors-and-testing): which errors to retry. # Keys URL: /code/api/guides/keys · Id: `page:code/api/guides/keys` > Five kinds of key reach api.sb, each issued by Identity for one Worker, narrowed by scope, rotated without downtime and revoked on the next call. A key is a credential [Identity](/code/platform/identity) issues to one [Worker](/business/nouns/worker), for one scope and one environment. Pick the kind by where the code runs. ## Kinds of key | Prefix | Kind | For | Lifetime | | --- | --- | --- | --- | | `sk_test_`, `sk_live_` | [Secret](/business/nouns/secret) key | Server code and unattended [Agents](/business/nouns/agent) | Until revoked | | `pk_test_`, `pk_live_` | Publishable key | A [Startup](/business/nouns/startup)'s own [Site](/business/nouns/site) and [App](/business/nouns/app), in the browser | Until revoked | | `rk_` | [Role](/business/nouns/role) session key | An Agent working one seat in a Role | 1 hour, renewed while the session runs | | `oat_` | OAuth access token | MCP clients and other apps a human approved | 1 hour, renewed by its refresh token | | `xt_` | Exchanged token | CI and deploy pipelines | 15 minutes | The `test` or `live` in a prefix picks the [environment](/code/cli/guides/environments). Every prefix is distinct, so a scanner recognizes a key on sight. ## Scopes narrow A key's scope is set when it is created and never widens. It names three things: which namespaces the key reaches, which [Verbs](/business/nouns/verb) it may run, and which environment it runs in. ```bash npx startup-builder keys create \ --name "price sync" \ --scope pricewatch.io \ --verbs "Dataset.get,Dataset.list,Order.get" \ --env live ``` A namespace scope is one Startup, a [Portfolio](/business/nouns/portfolio) query such as every Startup on one template, or the [Studio](/business/nouns/studio). A scope only narrows what its Worker may already do. A key for a Startup where its Worker holds no Role reaches nothing. ## Publishable keys `pricewatch.io` is a Startup that sells retail price data. Its pricing page calls `Order.place` from the browser with a `pk_live_` key. A publishable key runs only the Verbs a Startup marks public, and reads only published records. Each browser call records the [Visitor](/business/nouns/visitor) as `for` and throttles per Visitor. A leaked publishable key exposes nothing a page does not already show. ## Role session keys An Agent seated in a Role works under a Role session key, minted from its identity when a session starts. The key holds exactly that Role's [Permissions](/business/nouns/permission), [Mandate](/business/nouns/mandate) and [Limits](/business/nouns/limit). One Agent can hold seats in many Startups. Each seat gets its own key, so every [Action](/business/nouns/action) records which seat acted, and one seat's revocation leaves the others running. ## Machines without secrets A pipeline stores no key. It exchanges the OIDC token its runner already has for a 15-minute `xt_` token: ```bash npx startup-builder login --oidc --scope pricewatch.io --env live npx startup-builder do Version.deploy --json '{"version":"v42"}' --env live ``` The exchange checks the token's repository and branch against a trust rule on the namespace. A pull request from a fork gets nothing. ## Rotate, revoke, detect To rotate a secret key without downtime, roll it. `npx startup-builder keys roll key_price_sync --expire-in 24h` issues a new key and keeps the old one working for 24 hours. Deploy the new key, and the old one stops on schedule. To stop a key at once, revoke it. The next call returns `401` [unauthorized](/code/api/errors/unauthorized). Identity watches public code and pages for live secret keys. A leaked key is revoked within minutes, and the namespace's owner Role gets a [Task](/business/nouns/task) to deploy its replacement. Every key's creation, use, roll and revocation is an [Event](/business/nouns/event) in the namespace's [audit log](/systems/trust-and-governance/audit-log). ## Next - [Authentication](/code/api/guides/authentication): how a key's call is checked and attributed. - [Secrets](/code/platform/secrets): where code stores the outside credentials it uses. - [Idempotency](/code/api/guides/idempotency): make each keyed write safe to retry. # Modes URL: /code/api/guides/modes · Id: `page:code/api/guides/modes` > A Mode sets how a Verb runs and when the caller hears back; try stores nothing, send returns at once, and do waits for the finished Action. A [Mode](/business/nouns/mode) is how a caller invokes a [Verb](/business/nouns/verb): `try`, `send` or `do`. It decides whether the call is recorded and when the caller hears back. ## Three Modes | Mode | Recorded | The caller gets | HTTP status | | --- | --- | --- | --- | | `try` | No | The result or the error it would hit, at once | `200` | | `send` | Yes | A `pending` [Action](/business/nouns/action), at once, with its URL in `Location` | `202` | | `do` | Yes | The finished Action and its result | `200` | `try` runs every check and computes the result, then stores nothing. It suits lookups and previews: a tax estimate, a domain check, the refund a caller would get. `send` records the Action and returns before the work starts. It suits work measured in minutes or days, such as a contract review that a credentialed human finishes. `do` records the Action and holds the call until it ends. The caller writes straight-line code and gets the result, or the reason there is none. ## Defaults and choices Each Verb declares a default Mode and the Modes a caller may choose, and its reference lists both. `Order.refund` defaults to `do`, because the caller wants the refunded [Order](/business/nouns/order) back. A call that names a Mode the Verb does not accept returns [`mode-not-allowed`](/code/api/errors/mode-not-allowed). A Verb that accepts only `send` never blocks a caller, whatever the caller asks. ## Choosing a Mode on each Interface `clauseclear.com` is a [Services-as-Software](/products/templates/services-as-software) business that reviews vendor contracts for small firms. An agent reviews each contract, and a licensed attorney signs off. Its client places Orders in `send` Mode and moves on: **Ask** ```text Order a contract review and tell me when it is done. ``` **API** ```bash curl -i -X POST "https://api.sb/clauseclear.com/orders/place?mode=send" \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"offer":"offer_review"}' # HTTP/2 202 # Location: https://api.sb/clauseclear.com/actions/action_52 ``` **SDK** ```ts import { $ } from 'startup-builder' const action = await $.send.Order.place({ offer: 'offer_review' }) ``` **CLI** ```bash npx startup-builder do Order.place --send --json '{"offer":"offer_review"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.send.Order.place({ offer: 'offer_review' })" } } ``` The SDK also takes the Mode as an option: `$.Order.place(input, { mode: 'send' })`. Over MCP, the `do` tool's name is fixed, and the Mode still belongs to the call inside it. A `send` caller learns the outcome by reading the Action at `Location`, or by subscribing to its [Events](/business/nouns/event) through a [Watch](/business/nouns/watch) or a [stream](/code/sdk/guides/realtime). ## Try as a preview `try` on a Verb that writes is a dry run. The caller sees the record it would get, or the problem it would hit, and nothing changes. ```ts const preview = await $.try.Order.refund({ order: 'order_7', amount: { amount: 120, currency: 'USD' }, reason: 'Review missed the deadline' }) ``` On the API, `GET` on a Verb's route is the same preview. [Agents](/business/nouns/agent) preview every write that moves money, then commit with `do`. ## What the caller waits through A recorded call creates an [Action](/business/nouns/action) that starts `pending` and settles `done`, `failed`, `canceled` or `refused`. [Actions](/code/sdk/guides/actions) explains each status and each reason an Action waits. The Mode decides only how much of that wait the caller sits through. A `do` caller holds the connection until the Action settles; a `send` caller reads the outcome later. The clauseclear review, `Order.deliver`, waits as `awaitingWorker` until the attorney claims its [Task](/business/nouns/task), which can take hours. A one-way Verb, such as a refund, also waits out its [delay window](/agents/autonomy-levels/delay-windows) as `awaitingTime`. Nobody has to approve it: when the window closes, it runs. A refund over a [Limit](/business/nouns/limit) waits instead on an [Approval](/business/nouns/approval). In the SDK, a `do` call rejects when its Action ends `failed`, `refused` or `canceled`. To get the final Action whatever its status, await `.settled`: ```ts const action = await $.Order.refund({ order: 'order_7', reason: 'Review missed the deadline' }).settled if (action.status === 'refused') console.log(action.error?.fix) ``` ## Safe to repeat Send an [`Idempotency-Key`](/code/api/guides/idempotency) with every recorded call. A repeat after a dropped connection returns the first Action instead of starting a second. Every call, in every Mode, emits a usage Event that billing reads, so a billed call is never sampled. Streaming, batching and scheduling change how results arrive or when work runs; they are not Modes. ## Next - [Actions](/code/sdk/guides/actions): the record every `send` and `do` call creates. - [Webhooks](/code/api/guides/webhooks): hear the Events a `send` call produces. - [Errors and testing](/code/sdk/guides/errors-and-testing): what a `refused` or `failed` Action carries. # Pagination and filtering URL: /code/api/guides/pagination-and-filtering · Id: `page:code/api/guides/pagination-and-filtering` > Every list takes one where grammar, a sort and a keyset cursor, so a query pages the same way on every Interface and never skips a record. Every list on [api.sb](/code/platform/api-sb) returns one page at a time, newest first, behind a cursor. One `where` grammar filters it, and the same grammar selects [Events](/business/nouns/event) for [Watches](/business/nouns/watch). ## A first query `paperbill.io` is a [Headless SaaS](/products/templates/headless-saas) that sends and collects [Invoices](/business/nouns/invoice) for freelancers. Its collections screen asks for unpaid Invoices over $500, oldest due date first: **Ask** ```text Which unpaid invoices are over $500? Oldest due date first. ``` **API** ```bash curl -G https://api.sb/paperbill.io/invoices \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ --data-urlencode "where=paidAt = null and total.amount > 500" \ --data-urlencode "sort=due" \ --data-urlencode "limit=50" ``` **SDK** ```ts import { $ } from 'startup-builder' const page = await $.Invoice.list({ where: 'paidAt = null and total.amount > 500', sort: 'due', limit: 50, }) ``` **CLI** ```bash npx startup-builder do Invoice.list \ --json '{"where":"paidAt = null and total.amount > 500","sort":"due","limit":50}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Invoice.list({ where: 'paidAt = null and total.amount > 500', sort: 'due', limit: 50 })" } } ``` The response is a list [envelope](/code/api/guides/envelope): the page under `invoices`, the cursor in `meta.after`, and the next page in `links.next`. ## The where grammar A filter is one expression over the [Noun](/business/nouns/noun)'s properties. Dotted paths reach into objects and one level into related records: `total.amount`, `customer.country`. | Operator | Example | | --- | --- | | `=`, `!=` | `status = open` | | `>`, `>=`, `<`, `<=` | `due < 2026-11-01` | | `in` | `status in (open, overdue)` | | `contains` | `memo contains "retainer"` | | `= null`, `!= null` | `paidAt = null` | | `and`, `or`, `not`, parentheses | `(status = open or status = overdue) and total.amount > 500` | Values take the property's type: money compares on `amount` in its own currency, and dates accept ISO 8601. A filter on a property the Noun does not have fails with [`invalid-input`](/code/api/errors/invalid-input), naming the property. The SDK accepts the string or an object. An object's keys join with `and`, and each value is either a literal or an operator map such as `{ gt: 500 }`. The grammar is the platform's one selector language. A Watch selector `Invoice.paid where total.amount > 500` uses the same clause, so a filter tested on a list behaves identically on a live feed. ## Sorting `sort` takes a comma-separated list of properties. A leading minus sorts descending: `sort=-total.amount,due`. Without `sort`, a list returns newest first. Every sort ends with the record id as a tiebreaker, added for you. Two Invoices due the same day always come back in the same order. ## Cursors Lists page by keyset. The cursor encodes the last record's position in the sort, not an offset, so a record written mid-scan never shifts later pages or appears twice. To read the next page, pass `after` from the previous one, or follow `links.next`. A page without `after` is the last. Cursors are opaque and never expire, and each is bound to its query: reusing one with another `where` or `sort` returns `invalid-input`. `limit` sets the page size: 20 by default, 100 at most. To walk a whole collection, the SDK iterates pages for you: ```ts for await (const invoice of $.Invoice.list({ where: 'paidAt = null' }).all()) { await $.Invoice.collect({ invoice: invoice.$id }) } ``` ## Totals and facets A list returns no count unless asked, because counting a large collection costs a full scan. Add `total=true` and `meta.total` holds the count. It is exact up to 10,000 matches; above that it is an estimate, and `meta.totalExact` is `false`. `facets` returns a count per value for the properties you name, from the same snapshot as the total: ```bash curl -G https://api.sb/paperbill.io/invoices \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ --data-urlencode "where=paidAt = null" \ --data-urlencode "total=true" \ --data-urlencode "facets=status,customer.country" ``` `meta.facets.status` might read `{ "open": 41, "overdue": 9 }`, summing to `meta.total`. A filter panel built on facets never shows a count the list disagrees with. ## Shaping the result `fields` trims each record to the properties named: `fields=$id,total,due`. `$id` and `$type` always come back. `include` embeds related records, and `depth` follows them further, as the envelope describes. [Agents](/business/nouns/agent) pay for every token they read. A list call with `fields` and `Accept: text/markdown` returns the same page at a fraction of the size. ## Search `q` matches words across a Noun's text properties, ranked by relevance: `q=late fee`. Add `match=meaning` to rank by meaning instead, so `q=client refuses to pay` finds Invoices whose notes say "disputed". Both combine with `where`, and both page with the same cursors. ## Next - [Envelope](/code/api/guides/envelope): the list shape, `include` and `depth`. - [Webhooks](/code/api/guides/webhooks): the same `where` clause, on a Watch. - [Realtime](/code/sdk/guides/realtime): a query that stays open and streams its changes. # Standards URL: /code/api/guides/standards · Id: `page:code/api/guides/standards` > An Interface speaks a Standard through one translator the platform writes once; a Startup maps the Standard's operations onto its own Verbs. A [Standard](/business/nouns/standard) is an outside spec an [Interface](/business/nouns/interface) also speaks, so its callers reach a [Product](/business/nouns/product)'s [Verbs](/business/nouns/verb) unchanged. The platform writes each Standard once as a translator, and a [Startup](/business/nouns/startup) maps the Standard's operations onto its own Verbs. ## Why Standards exist Every route on every API compiles from a Verb, and nobody writes a route by hand. That holds while every caller speaks the Product's own grammar. Some callers arrive in a shape someone else defined. A model client posts chat completions, a [Customer](/business/nouns/customer)'s identity provider provisions users with SCIM, and a file tool speaks S3. A Standard answers those callers without opening the door to hand-written routes. A path that no Standard covers is refused. ## Declare a mapping `listsmith.ai` sells an [Agent](/business/nouns/agent) that writes product listings through its own Verb, `Listing.write`. Its developer Customers already call models through chat-completions clients and want to switch by changing the base URL. The Startup's API Interface declares one mapping in `conformsTo`: ```ts conformsTo: [ { standard: 'openai-chat', operations: { 'chat.completions.create': 'Listing.write' } }, ] ``` A Customer's client then posts to `https://api.listsmith.ai/v1/chat/completions` with its usual request and reads the usual response. The Standard's path sits on the Startup's own API host, under its [Publication](/business/nouns/publication). ## What the translator does The translator accepts the request in the Standard's shape and runs the mapped Verb as an ordinary [Action](/business/nouns/action). Everything a native call gets, the translated call gets: | On every translated call | Detail | | --- | --- | | Keys and [Permissions](/business/nouns/permission) | The caller's key and [Role](/business/nouns/role), checked as on any route | | [Limits](/business/nouns/limit) and [Meters](/business/nouns/meter) | The same Limits apply, and usage meters against the caller's [Subscription](/business/nouns/subscription) | | [Events](/business/nouns/event) and history | One Action, its Events, and its record, kept forever | | Errors | Each refusal returned in the Standard's own error shape | A Startup writes no translation code. A second Agent Product declares its own mapping and gets the same translator, so a fix to it reaches every Startup that speaks the Standard. ## Standards the platform speaks | Standard | Callers | Maps onto | | --- | --- | --- | | SCIM 2.0 | A Customer's identity provider provisioning its people | [Tenant.invite](/business/nouns/tenant/invite) and membership Verbs | | Chat completions | Model clients calling an Agent Product | The Agent's own Verb, such as `Listing.write` | | S3 | Clients that read and write stored objects | [File](/business/nouns/file) Verbs | | OIDC discovery | Clients signing in to a Startup as an authorization server | The Startup's sign-in | | RSS | Feed readers following a [Site](/business/nouns/site) | [Page](/business/nouns/page) lists | | Standard Webhooks | Receivers verifying deliveries | Every [Watch](/business/nouns/watch) delivery ([Webhooks](/code/api/guides/webhooks)) | A Standard records its `spec`, the `path` where its translator answers, and the `operations` it accepts. List them with `Standard.list`. # Throttling URL: /code/api/guides/throttling · Id: `page:code/api/guides/throttling` > Throttles shield api.sb from request floods with a 429 a caller waits out, and a Limit is a different gate. Throttling protects [api.sb](/code/platform/api-sb) from too many requests too fast. A throttled request answers `429` before anything is recorded: no [Action](/business/nouns/action), no [Approval](/business/nouns/approval), no charge. ## Throttles are not Limits A throttle and a [Limit](/business/nouns/limit) both say "not now", for different reasons. A throttle guards the platform against a flood. A Limit is a business decision about how much a [Worker](/business/nouns/worker), [Mandate](/business/nouns/mandate) or [Entitlement](/business/nouns/entitlement) may spend or use. | | Throttle | Limit | | --- | --- | --- | | Protects | The platform and its neighbors | The business | | Counts | Requests per second, and calls in flight | Money, units, or a rate per day or month | | On breach | `429` and `Retry-After`; nothing recorded | The Action waits `awaitingAction` on an Approval | | Resolved by | Waiting | Someone with authority approves, or the Limit rises | `tidewise.dev` sells tide predictions by API. Its [Customers](/business/nouns/customer)' plans allow 10,000 calls a month: a Limit, metered and billed. The burst of 500 calls a script fires in one second meets a throttle, and the script slows down. ## Read the headers Every response carries the caller's current window: ```http RateLimit-Limit: 100 RateLimit-Remaining: 12 RateLimit-Reset: 1 ``` A throttled request returns the [rate-limited](/code/api/errors/rate-limited) problem with `Retry-After` in seconds: ```json { "type": "https://startupbuilder.dev/code/api/errors/rate-limited", "title": "Rate limited", "status": 429, "detail": "Key key_tidewise_sync sent 100 requests in the last second.", "fix": "Wait the number of seconds in the `Retry-After` header, then retry." } ``` ## Default throttles | Throttle | Default | | --- | --- | | Requests per live key | 100 per second | | Requests per test key | 25 per second | | Requests per namespace, all keys together | 1,000 per second | | `do` calls in flight per key | 50 | | Requests per visitor on a publishable key | 10 per second | Each throttle is a [Setting](/business/nouns/setting) on the namespace, and a [Startup](/business/nouns/startup) tightens any of them for its own keys. It throttles its own Customers the same way. A plan's per-second rate answers `429`, while its monthly count stays a Limit. ## Queued work is never throttled Throttles count requests, not work. Once a `send` call is accepted, its Action waits `queued` and runs at the namespace's pace, never answering `429` later. To move 50,000 records, `send` them in batches of 100. The queue absorbs the burst, and each Action settles in order. ## Back off and retry The SDK and the CLI retry a `429` on their own. They wait `Retry-After` plus random jitter, up to three times, with the same idempotency key. Over MCP, the tool result carries the same problem, and an [Agent](/business/nouns/agent) waits before its next call. A hand-written client does the same: ```ts async function call(req: () => Promise, attempts = 3): Promise { const res = await req() if (res.status !== 429 || attempts === 0) return res const wait = Number(res.headers.get('Retry-After') ?? 1) * 1000 await new Promise((r) => setTimeout(r, wait + Math.random() * 250)) return call(req, attempts - 1) } ``` Never retry a Limit. An Action over a Limit is already waiting for its Approval, and a retry returns that same Action. ## Next - [Idempotency](/code/api/guides/idempotency): make every retry safe. - [Rate limits](/code/platform/rate-limits): the capability that meters calls against Limits. - [Mandates and Limits](/agents/mandates-and-limits): how Limits bound an Agent's authority. # Versioning URL: /code/api/guides/versioning · Id: `page:code/api/guides/versioning` > The api.sb contract is version 1; the package major names it, additive changes reach it at once, and a breaking change ships as a new major. The [api.sb](/code/platform/api-sb) contract is version 1. [openapi.json](https://startupbuilder.dev/openapi.json) states it as `info.version`, and every release of `startup-builder@1` calls it. ## Where the version lives No URL carries the platform version, and no flag selects one. Code pins it by pinning the package major. | [Interface](/business/nouns/interface) | Pinned by | | --- | --- | | API | `https://api.sb/{namespace}` serves version 1, as openapi.json describes it | | SDK | The package major: `startup-builder@1` | | CLI | The same package: `npx startup-builder@1` | | MCP | `https://api.sb/mcp` serves the tools of version 1 | ```bash npm install startup-builder@1 ``` ## What counts as breaking A breaking change is any change that can make correct code fail. | Breaking | Additive | | --- | --- | | Removing or renaming a route, field, [Verb](/business/nouns/verb), [Event](/business/nouns/event), error type or header | A new route, [Noun](/business/nouns/noun), Verb, Event or error type | | Changing a field's type, unit or meaning | A new field in a response | | Making an optional input required | A new optional input | | Narrowing an input's accepted values | A new value in a response field's set | | Changing a status code, a default [Mode](/business/nouns/mode) or a page-size default | A new response header | Additive changes reach version 1 as they ship. Clients ignore fields they do not know and handle values they have not seen, so additive changes never break them. ## A breaking change is a new major A breaking change ships only as the next major: a new `info.version` and a new major of `startup-builder`. Code on `startup-builder@1` keeps calling version 1. Inside the newest version, a replaced form is deleted, not deprecated: no warnings, no sunset dates, no second way to do one thing. ## A Startup's own API A [Live](/business/lifecycle/states/live) [Startup](/business/nouns/startup)'s own Nouns and Verbs carry their own version, which its [Customers](/business/nouns/customer)' code relies on. Each [Tenant](/business/nouns/tenant)'s keys answer at the Tenant's `apiVersion`, and a path can name a version after the namespace: ```text https://api.sb/transcribe.fm/v3/transcripts ``` [Tenant.pin](/business/nouns/tenant/pin) moves a Tenant's keys to another version once a call with its test key passes there. Each [Watch](/business/nouns/watch) keeps the version current when it was created. [Compatibility](/code/builders/software/compatibility) explains how a Startup versions its own API. ## Upgrading The [Changelog](/changelog) states the current contract and logs each change to it. To take a new major, install it where the `test` key runs, run the tests, then deploy with the `live` key. ## Next - [The response envelope](/code/api/guides/envelope): the shape version 1 serves. - [Compatibility](/code/builders/software/compatibility): a Live Startup's own versions. - [SDK](/code/sdk): the package that names the version. # Webhooks URL: /code/api/guides/webhooks · Id: `page:code/api/guides/webhooks` > A Watch posts every Event a selector matches to your URL, signed, retried for three days, ordered by sequence and replayable from any point. A webhook is a [Watch](/business/nouns/watch): a standing request to POST every [Event](/business/nouns/event) a selector matches to a URL. Deliveries are signed, retried until acknowledged, numbered in order and replayable. ## Events are the feed Every [Action](/business/nouns/action) that writes a record emits an Event named for the record and the past tense of its [Verb](/business/nouns/verb): `Order.placed`, `Order.delivered`, `Invoice.paid`. Each Verb's reference names its Event, and reads emit none. A Watch subscribes to those names, so there is no separate webhook catalog to learn. Anything a caller can do through the API, a Watch can hear. ## Create a Watch `listingcraft.co` is a [Services-as-Software](/products/templates/services-as-software) business that writes rental listings for property managers. Each property manager's software wants to know the moment its listing is ready, so it registers a Watch with its own key: ```bash curl -X POST https://api.sb/listingcraft.co/watches \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"selector":"Order.delivered","url":"https://pm.example/hooks/listings"}' ``` The response holds the Watch and its signing secret: ```json { "api": "https://api.sb/listingcraft.co", "watch": { "$id": "https://api.sb/listingcraft.co/watches/watch_1", "$type": "Watch", "selector": "Order.delivered", "url": "https://pm.example/hooks/listings" }, "secret": "whsec_4f9c2a7e1b8d3f6a0c5e9b2d7a4f1c8e", "links": { "self": "https://api.sb/listingcraft.co/watches/watch_1" } } ``` The secret appears once, and no read returns it again: store it beside the receiver. A selector names one Event, `Order.delivered`, or every Event of a [Noun](/business/nouns/noun), `Order.*`. A `where` clause narrows it with the [list filter grammar](/code/api/guides/pagination-and-filtering): `Order.delivered where total.amount > 200`. A Watch hears only what its key may read. The property manager's key reaches its own [Tenant](/business/nouns/tenant), so its Watch never sees another manager's [Orders](/business/nouns/order). A Watch belongs to one [environment](/code/cli/guides/environments), and a test key's Watch hears only test Events. ## The delivery Each delivery is one Event, posted as JSON: ```json { "$id": "https://api.sb/listingcraft.co/events/event_8812", "$type": "Event", "name": "Order.delivered", "at": "2026-10-22T12:00:00Z", "seq": 8812, "data": { "order": { "$id": "https://api.sb/listingcraft.co/orders/order_31", "$type": "Order", "status": "fulfilled" } } } ``` `data` holds the record as the Action left it, in the shape the API returns. The `$id` names the [Startup](/business/nouns/startup), so one receiver can serve many. `seq` is the Event's position in the namespace, increasing by one per Event. A Watch created with `"payload":"thin"` sends only the record's versioned address, `order_31@v4`, and the receiver reads the rest. Choose thin deliveries when the receiver re-reads anyway, or when the record holds personal data that should not sit in a receiver's logs. ## Verify the signature Every delivery carries a `StartupBuilder-Signature` header: a timestamp `t` and one or more `v1` signatures. ```text StartupBuilder-Signature: t=1792670400,v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd ``` `verifyWebhook` from the SDK checks it against the raw body and the Watch's signing secret, and returns the Event. It throws when no signature matches, or when the newest is older than five minutes. ```ts import { verifyWebhook } from 'startup-builder' export async function POST(request: Request) { let event try { event = verifyWebhook(await request.text(), request.headers.get('StartupBuilder-Signature') ?? '', process.env.WATCH_SECRET ?? '') } catch { return new Response('bad signature', { status: 400 }) } if (event.name === 'Order.delivered') console.log(event.data.order.$id) return new Response(null, { status: 204 }) } ``` In another language, check it by hand. Each `v1` is a hex HMAC-SHA256 of `t`, a dot and the raw body, keyed with the signing secret. Compare in constant time, and accept the delivery when any `v1` matches. Verify against the raw bytes, before any JSON parser touches them. Reject anything older than five minutes, so a captured request replayed later fails. To change a secret without downtime, [rotate](/business/nouns/watch/rotate) it. For the next 24 hours each delivery carries two `v1` signatures, one per secret. Deploy the new secret to the receiver within that window, and nothing fails. ## Acknowledge and retry Answer any `2xx` within 10 seconds to acknowledge a delivery. Queue the work and answer first: a slow handler looks like a failure and earns a retry. An unacknowledged delivery retries 12 times over three days: after 1 minute, 5 minutes, 30 minutes, 2 hours, 6 hours, then every 12 hours. Each try is recorded on the Watch with its status code and response time, so the receiver's owner sees exactly what failed. A Watch whose deliveries have all failed for three days [pauses](/business/nouns/watch/pause) itself and notifies the Startup's [Reliability Engineer](/agents/engineering/reliability-engineer). Its Events keep queuing. [Resume](/business/nouns/watch/resume) it once the receiver is fixed, and the held Events arrive oldest first. ## Order, duplicates and replay Deliveries arrive at least once, and retries can arrive out of turn. Store each Event's `$id` and skip one you have seen. When order matters, compare `seq`, or read the record itself. To recover from an outage longer than three days, or to load a new receiver with history, [replay](/business/nouns/watch/replay) the Watch from a point in time. Every matching Event since then arrives again, signed as the first time. Events are kept forever, so any point works. ## Inbound webhooks Outside services push into a Startup through the reverse door. Each [Integration](/business/nouns/integration) has one inbound URL, `https://api.sb//integrations//inbound`. The platform checks the sender's signature with the Integration's credentials, stores the raw body, and writes an Event before any [Workflow](/business/nouns/workflow) acts. A chargeback from the card network arrives as `Order.disputed`, and a forged request never becomes an Event. Inbound Events take the same selectors, [Triggers](/business/nouns/trigger), Watches and replays as any other. ## Next - [Realtime](/code/sdk/guides/realtime): the same Events over an open connection, without a public URL. - [Errors and testing](/code/sdk/guides/errors-and-testing): fire test Events at a receiver on your laptop. - [Event streams](/code/platform/event-streams): the capability every Watch reads from. # API URL: /code/api · Id: `page:code/api` > How api.sb works, traced through one data business. The [StartupBuilder](/code/builders/startup) API serves every [Startup](/business/nouns/startup) at [api.sb](/code/platform/api-sb) as plain HTTPS and JSON. Every route is compiled from a [Verb](/business/nouns/verb), so learning one route teaches them all. ## One namespace per Startup A Startup's namespace is its [Domain](/business/nouns/domain). `openhours.dev` sells verified opening hours for four million storefronts to developers and the coding agents that work for them, at $0.002 per lookup. Every record it owns lives under `https://api.sb/openhours.dev`. The namespace holds the platform's [Nouns](/business/nouns/noun), such as [Offers](/business/nouns/offer) and [Orders](/business/nouns/order), and the Startup's own. `openhours.dev` declares a `Storefront` Noun, so `/openhours.dev/storefronts` serves its data. `https://api.sb/openhours.dev/openapi.json` describes both, and its [Customers](/business/nouns/customer) generate clients from it. ## Routes are compiled from Verbs Nobody writes a route by hand. Each Noun gets a collection named by its plural, and each Verb gets a `POST` route named by itself: | Call | Route | Name | | --- | --- | --- | | List storefronts | `GET /openhours.dev/storefronts` | `Storefront.list` | | Read one Offer | `GET /openhours.dev/offers/offer_1` | `Offer.get` | | Place an Order | `POST /openhours.dev/orders/place` | `Order.place` | | Subscribe to an Offer | `POST /openhours.dev/offers/offer_1/subscribe` | `Offer.subscribe` | A Verb that acts on an existing record takes its id in the path. A Verb that brings a record into being sits on the collection. `GET` on any Verb route previews it and stores nothing. The operation name is the contract. `Offer.subscribe` is the OpenAPI operationId, the SDK method, the CLI command, the MCP call, and the rate-limit key. Adding a Verb to a Noun adds all five, its [Event](/business/nouns/event), and its docs row in one write, so no [Interface](/business/nouns/interface) lags another. ## Keys Every request carries a key as a bearer token. The key names the namespace, and the [Permissions](/business/nouns/permission) of its [Role](/business/nouns/role) decide which Verbs it may run. [Limits](/business/nouns/limit) bound how far each one goes. ```bash curl "https://api.sb/openhours.dev/storefronts?city=Lisbon&limit=20" \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` A key that starts `sk_test_` reaches the test environment, where no money moves and no message leaves. A `sk_live_` key reaches live. Code moves from one to the other unchanged, as [authentication](/code/api/guides/authentication) and [environments](/code/cli/guides/environments) explain. ## Reads return an envelope Every response is one JSON object with the same keys. Reading an Offer returns the record under its Noun's name, plus links to read and Verbs to run: ```json { "api": "https://api.sb/openhours.dev", "$type": "Offer", "$id": "https://api.sb/openhours.dev/offers/offer_1", "offer": { "$id": "https://api.sb/openhours.dev/offers/offer_1", "$type": "Offer", "price": { "amount": 0.002, "currency": "USD" }, "interval": "month", "terms": "Verified opening hours for any storefront, billed per lookup." }, "links": { "self": "https://api.sb/openhours.dev/offers/offer_1", "up": "https://api.sb/openhours.dev/offers" }, "actions": { "subscribe": "https://api.sb/openhours.dev/offers/offer_1/subscribe" } } ``` `actions` lists only the Verbs this caller may run on this record in its current state. A client that follows `actions` never calls a Verb the record refuses, and an agent never needs the state rules in its prompt. The [envelope](/code/api/guides/envelope) covers lists, cursors, and every key. ## Writes return an Action Every write is an [Action](/business/nouns/action): a durable record of one Verb, its input, its status, and who ran it for whom. The response carries the Action beside the record it changed: ```bash curl -X POST https://api.sb/openhours.dev/offers/offer_1/subscribe \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Idempotency-Key: signup-91c2" \ -H "Content-Type: application/json" \ -d '{"quantity":1}' ``` ```json { "api": "https://api.sb/openhours.dev", "action": { "$id": "https://api.sb/openhours.dev/actions/action_1", "operation": "Offer.subscribe", "status": "done" }, "subscription": { "$id": "https://api.sb/openhours.dev/subscriptions/subscription_1", "$type": "Subscription", "status": "active" }, "links": { "self": "https://api.sb/openhours.dev/actions/action_1" } } ``` The [Mode](/business/nouns/mode) decides when the caller hears back. `try` runs and stores nothing, `send` returns a `pending` Action at once, and `do` waits for the finish. A `pending` Action names its reason, such as `awaitingInput` or `awaitingTime`, so the caller knows whether to wait or act. An Action over a Limit stays `pending` until its [Approval](/business/nouns/approval) is decided. A retry with the same `Idempotency-Key` returns the first Action and runs nothing. [Modes](/code/api/guides/modes) covers each case. ## Errors name the fix Every error is an RFC 9457 problem whose `type` is a page on this site. Its `fix` and `next` fields carry the remedy, so an agent recovers without a search. A test subscription to an Offer that is still a draft is refused: ```json { "type": "https://startupbuilder.dev/code/api/errors/refused", "title": "Refused", "status": 422, "detail": "Offer offer_2 is a draft, so nobody can subscribe to it.", "fix": "Publish the Offer, then subscribe again.", "next": "https://api.sb/openhours.dev/offers/offer_2/publish", "instance": "https://api.sb/openhours.dev/actions/action_2" } ``` A refused Action keeps its record forever. A retry runs a new Action linked to the old one, and history is never rewritten. [Errors and testing](/code/sdk/guides/errors-and-testing) lists every problem type and how to reproduce it in test. ## Events Every write emits one Event, named by its Noun and the past tense of its Verb: `Offer.subscribed`, `Order.paid`. A [Watch](/business/nouns/watch) delivers the Events a selector matches to a URL: ```bash curl -X POST https://api.sb/openhours.dev/watches \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"selector":"Offer.subscribed","url":"https://openhours.dev/hooks/signups"}' ``` Each delivery is a signed `POST`, retried until acknowledged and replayable from any point. [Webhooks](/code/api/guides/webhooks) shows how to verify the signature. The [SDK](/code/sdk) makes the same calls as typed TypeScript. # Limits and quotas URL: /code/api/limits · Id: `page:code/api/limits` > Requests per second, page sizes, token lifetimes, webhook retries and cache sizes, each with the page that explains it. Every platform throttle, size, timeout and retry schedule in one table per area. A throttle protects the platform and answers `429`; a [Limit](/business/nouns/limit) protects the business and waits on an [Approval](/business/nouns/approval) ([throttling](/code/api/guides/throttling)). ## Requests | Throttle | Default | | --- | --- | | Requests per live key | 100 per second | | Requests per test key | 25 per second | | Requests per namespace, all keys together | 1,000 per second | | `do` calls in flight per key | 50 | | Requests per visitor on a publishable key | 10 per second | A throttled call returns `429` with `Retry-After` and records nothing. To move a large batch, `send` it in batches of 100 and let the queue absorb the burst. ## Lists and writes | What | Limit | Explained in | | --- | --- | --- | | Records per call, `limit` | 20 by default, 100 at most | [Pagination and filtering](/code/api/guides/pagination-and-filtering) | | `meta.total` | Exact up to 10,000 matches, then an estimate | [Pagination and filtering](/code/api/guides/pagination-and-filtering) | | Cursors | Never expire; bound to their query | [Pagination and filtering](/code/api/guides/pagination-and-filtering) | | Idempotency key | Up to 255 characters, held forever | [Idempotency](/code/api/guides/idempotency) | | Approval wait | 48 hours before it escalates, set by `approvalHours` | [`startup.ts`](/code/startup-ts#approval-hours) | ## Keys and sessions | What | Lifetime | Explained in | | --- | --- | --- | | CI token from `login --oidc` | 15 minutes | [Keys](/code/api/guides/keys#machines-without-secrets) | | A rolled key's predecessor | Until its `--expire-in`, such as `24h` | [Keys](/code/api/guides/keys) | | A claimed [Task](/business/nouns/task) | A 15-minute lease, then back to the queue | [CLI](/code/cli) | ## Deliveries and streams | What | Limit | Explained in | | --- | --- | --- | | Webhook acknowledgment | Any `2xx` within 10 seconds | [Webhooks](/code/api/guides/webhooks) | | Webhook retries | 12 tries over three days: 1 minute, 5 minutes, 30 minutes, 2 hours, 6 hours, then every 12 hours | [Webhooks](/code/api/guides/webhooks) | | Signing secret rotation | Both signatures for 24 hours | [Webhooks](/code/api/guides/webhooks) | | Stream heartbeat | A comment line every 15 seconds; reconnect after 45 silent seconds | [Realtime](/code/sdk/guides/realtime) | | [Event](/business/nouns/event) retention | Forever, ordered by `seq` per namespace | [Event streams](/code/platform/event-streams) | ## Storage, cache and queues | What | Limit | Explained in | | --- | --- | --- | | [Share](/business/nouns/share) link | Signed, and expires after 7 days by default | [Storage](/code/platform/storage) | | Cache value | 1 MB at most; expires after one hour by default | [KV cache](/code/platform/kv-cache) | | Queue retries | 5 attempts over 24 hours by default, each a new [Action](/business/nouns/action) | [Queues](/code/platform/queues) | | Actions | Kept forever, so a replayed idempotency key returns its first Action a year later | [Idempotency](/code/api/guides/idempotency) | # API routes URL: /code/api/reference · Id: `interface:api` > Every StartupBuilder operation as an api.sb route, grouped by Noun. Every [Verb](/business/nouns/verb) on every [Noun](/business/nouns/noun) as an [api.sb](/code/platform/api-sb) route, with the [Event](/business/nouns/event) it emits. ### Grammar ```text POST /{namespace}/{nouns} create GET /{namespace}/{nouns} list GET /{namespace}/{nouns}/{id} get PATCH /{namespace}/{nouns}/{id} update DELETE /{namespace}/{nouns}/{id} delete POST /{namespace}/{nouns}/{id}/{verb} a Verb on one record POST /{namespace}/{nouns}/{verb} a Verb on the collection ``` The [API spec](/code/api/spec) covers authentication, Modes, and errors. ### Access Level | Operation | Route | Event | | --- | --- | --- | | [AccessLevel.get](/business/nouns/access-level/get?interface=api) | `GET /{namespace}/access-levels/{id}` | None. | | [AccessLevel.list](/business/nouns/access-level/list?interface=api) | `GET /{namespace}/access-levels` | None. | ### Account | Operation | Route | Event | | --- | --- | --- | | [Account.get](/business/nouns/account/get?interface=api) | `GET /{namespace}/accounts/{id}` | None. | | [Account.list](/business/nouns/account/list?interface=api) | `GET /{namespace}/accounts` | None. | | [Account.payout](/business/nouns/account/payout?interface=api) | `POST /{namespace}/accounts/{account}/payout` | [`Account.paidOut`](/business/events/Account.paidOut) | | [Account.sweep](/business/nouns/account/sweep?interface=api) | `POST /{namespace}/accounts/{from}/sweep` | [`Account.swept`](/business/events/Account.swept) | ### Acquisition | Operation | Route | Event | | --- | --- | --- | | [Acquisition.get](/business/nouns/acquisition/get?interface=api) | `GET /{namespace}/acquisitions/{id}` | None. | | [Acquisition.list](/business/nouns/acquisition/list?interface=api) | `GET /{namespace}/acquisitions` | None. | ### Action | Operation | Route | Event | | --- | --- | --- | | [Action.create](/business/nouns/action/create?interface=api) | `POST /{namespace}/actions` | `Action.created` | | [Action.get](/business/nouns/action/get?interface=api) | `GET /{namespace}/actions/{id}` | None. | | [Action.list](/business/nouns/action/list?interface=api) | `GET /{namespace}/actions` | None. | | [Action.answer](/business/nouns/action/answer?interface=api) | `POST /{namespace}/actions/{action}/answer` | [`Action.answered`](/business/events/Action.answered) | | [Action.ask](/business/nouns/action/ask?interface=api) | `POST /{namespace}/actions/{action}/ask` | [`Action.asked`](/business/events/Action.asked) | | [Action.attest](/business/nouns/action/attest?interface=api) | `POST /{namespace}/actions/{action}/attest` | [`Action.attested`](/business/events/Action.attested) | | [Action.cancel](/business/nouns/action/cancel?interface=api) | `POST /{namespace}/actions/{action}/cancel` | [`Action.canceled`](/business/events/Action.canceled) | | [Action.evaluate](/business/nouns/action/evaluate?interface=api) | `POST /{namespace}/actions/{action}/evaluate` | [`Action.evaluated`](/business/events/Action.evaluated) | | [Action.pause](/business/nouns/action/pause?interface=api) | `POST /{namespace}/actions/{action}/pause` | [`Action.paused`](/business/events/Action.paused) | | [Action.redirect](/business/nouns/action/redirect?interface=api) | `POST /{namespace}/actions/{action}/redirect` | [`Action.redirected`](/business/events/Action.redirected) | | [Action.resume](/business/nouns/action/resume?interface=api) | `POST /{namespace}/actions/{action}/resume` | [`Action.resumed`](/business/events/Action.resumed) | | [Action.retry](/business/nouns/action/retry?interface=api) | `POST /{namespace}/actions/{action}/retry` | [`Action.retried`](/business/events/Action.retried) | ### Ad | Operation | Route | Event | | --- | --- | --- | | [Ad.create](/business/nouns/ad/create?interface=api) | `POST /{namespace}/ads` | `Ad.created` | | [Ad.get](/business/nouns/ad/get?interface=api) | `GET /{namespace}/ads/{id}` | None. | | [Ad.list](/business/nouns/ad/list?interface=api) | `GET /{namespace}/ads` | None. | | [Ad.update](/business/nouns/ad/update?interface=api) | `PATCH /{namespace}/ads/{id}` | `Ad.updated` | | [Ad.delete](/business/nouns/ad/delete?interface=api) | `DELETE /{namespace}/ads/{id}` | `Ad.deleted` | ### Agent | Operation | Route | Event | | --- | --- | --- | | [Agent.create](/business/nouns/agent/create?interface=api) | `POST /{namespace}/agents` | `Agent.created` | | [Agent.get](/business/nouns/agent/get?interface=api) | `GET /{namespace}/agents/{id}` | None. | | [Agent.list](/business/nouns/agent/list?interface=api) | `GET /{namespace}/agents` | None. | | [Agent.update](/business/nouns/agent/update?interface=api) | `PATCH /{namespace}/agents/{id}` | `Agent.updated` | | [Agent.delete](/business/nouns/agent/delete?interface=api) | `DELETE /{namespace}/agents/{id}` | `Agent.deleted` | | [Agent.mint](/business/nouns/agent/mint?interface=api) | `POST /{namespace}/agents/mint` | [`Agent.minted`](/business/events/Agent.minted) | | [Agent.pause](/business/nouns/agent/pause?interface=api) | `POST /{namespace}/agents/pause` | [`Agent.paused`](/business/events/Agent.paused) | | [Agent.resume](/business/nouns/agent/resume?interface=api) | `POST /{namespace}/agents/{agent}/resume` | [`Agent.resumed`](/business/events/Agent.resumed) | | [Agent.retire](/business/nouns/agent/retire?interface=api) | `POST /{namespace}/agents/{agent}/retire` | [`Agent.retired`](/business/events/Agent.retired) | ### Agreement | Operation | Route | Event | | --- | --- | --- | | [Agreement.create](/business/nouns/agreement/create?interface=api) | `POST /{namespace}/agreements` | `Agreement.created` | | [Agreement.get](/business/nouns/agreement/get?interface=api) | `GET /{namespace}/agreements/{id}` | None. | | [Agreement.list](/business/nouns/agreement/list?interface=api) | `GET /{namespace}/agreements` | None. | | [Agreement.update](/business/nouns/agreement/update?interface=api) | `PATCH /{namespace}/agreements/{id}` | `Agreement.updated` | | [Agreement.sign](/business/nouns/agreement/sign?interface=api) | `POST /{namespace}/agreements/{agreement}/sign` | [`Agreement.signed`](/business/events/Agreement.signed) | | [Agreement.terminate](/business/nouns/agreement/terminate?interface=api) | `POST /{namespace}/agreements/{agreement}/terminate` | [`Agreement.terminated`](/business/events/Agreement.terminated) | ### API Key | Operation | Route | Event | | --- | --- | --- | | [APIKey.get](/business/nouns/api-key/get?interface=api) | `GET /{namespace}/api-keys/{id}` | None. | | [APIKey.list](/business/nouns/api-key/list?interface=api) | `GET /{namespace}/api-keys` | None. | | [APIKey.issue](/business/nouns/api-key/issue?interface=api) | `POST /{namespace}/api-keys/issue` | [`APIKey.issued`](/business/events/APIKey.issued) | | [APIKey.revoke](/business/nouns/api-key/revoke?interface=api) | `POST /{namespace}/api-keys/{apiKey}/revoke` | [`APIKey.revoked`](/business/events/APIKey.revoked) | | [APIKey.roll](/business/nouns/api-key/roll?interface=api) | `POST /{namespace}/api-keys/{apiKey}/roll` | [`APIKey.rolled`](/business/events/APIKey.rolled) | ### App | Operation | Route | Event | | --- | --- | --- | | [App.publish](/business/nouns/app/publish?interface=api) | `POST /{namespace}/apps/{app}/publish` | [`App.published`](/business/events/App.published) | ### Approval | Operation | Route | Event | | --- | --- | --- | | [Approval.create](/business/nouns/approval/create?interface=api) | `POST /{namespace}/approvals` | `Approval.created` | | [Approval.get](/business/nouns/approval/get?interface=api) | `GET /{namespace}/approvals/{id}` | None. | | [Approval.list](/business/nouns/approval/list?interface=api) | `GET /{namespace}/approvals` | None. | | [Approval.update](/business/nouns/approval/update?interface=api) | `PATCH /{namespace}/approvals/{id}` | `Approval.updated` | | [Approval.delete](/business/nouns/approval/delete?interface=api) | `DELETE /{namespace}/approvals/{id}` | `Approval.deleted` | | [Approval.approve](/business/nouns/approval/approve?interface=api) | `POST /{namespace}/approvals/{approval}/approve` | [`Approval.approved`](/business/events/Approval.approved) | | [Approval.refuse](/business/nouns/approval/refuse?interface=api) | `POST /{namespace}/approvals/{approval}/refuse` | [`Approval.refused`](/business/events/Approval.refused) | ### Attestation | Operation | Route | Event | | --- | --- | --- | | [Attestation.create](/business/nouns/attestation/create?interface=api) | `POST /{namespace}/attestations` | `Attestation.created` | | [Attestation.get](/business/nouns/attestation/get?interface=api) | `GET /{namespace}/attestations/{id}` | None. | | [Attestation.list](/business/nouns/attestation/list?interface=api) | `GET /{namespace}/attestations` | None. | ### Audience | Operation | Route | Event | | --- | --- | --- | | [Audience.create](/business/nouns/audience/create?interface=api) | `POST /{namespace}/audiences` | `Audience.created` | | [Audience.get](/business/nouns/audience/get?interface=api) | `GET /{namespace}/audiences/{id}` | None. | | [Audience.list](/business/nouns/audience/list?interface=api) | `GET /{namespace}/audiences` | None. | | [Audience.update](/business/nouns/audience/update?interface=api) | `PATCH /{namespace}/audiences/{id}` | `Audience.updated` | | [Audience.delete](/business/nouns/audience/delete?interface=api) | `DELETE /{namespace}/audiences/{id}` | `Audience.deleted` | ### Audit | Operation | Route | Event | | --- | --- | --- | | [Audit.get](/business/nouns/audit/get?interface=api) | `GET /{namespace}/audits/{id}` | None. | | [Audit.list](/business/nouns/audit/list?interface=api) | `GET /{namespace}/audits` | None. | ### Bill | Operation | Route | Event | | --- | --- | --- | | [Bill.create](/business/nouns/bill/create?interface=api) | `POST /{namespace}/bills` | `Bill.created` | | [Bill.get](/business/nouns/bill/get?interface=api) | `GET /{namespace}/bills/{id}` | None. | | [Bill.list](/business/nouns/bill/list?interface=api) | `GET /{namespace}/bills` | None. | | [Bill.update](/business/nouns/bill/update?interface=api) | `PATCH /{namespace}/bills/{id}` | `Bill.updated` | | [Bill.approve](/business/nouns/bill/approve?interface=api) | `POST /{namespace}/bills/{bill}/approve` | [`Bill.approved`](/business/events/Bill.approved) | | [Bill.pay](/business/nouns/bill/pay?interface=api) | `POST /{namespace}/bills/{bill}/pay` | [`Bill.paid`](/business/events/Bill.paid) | ### Brand | Operation | Route | Event | | --- | --- | --- | | [Brand.create](/business/nouns/brand/create?interface=api) | `POST /{namespace}/brands` | `Brand.created` | | [Brand.get](/business/nouns/brand/get?interface=api) | `GET /{namespace}/brands/{id}` | None. | | [Brand.list](/business/nouns/brand/list?interface=api) | `GET /{namespace}/brands` | None. | | [Brand.update](/business/nouns/brand/update?interface=api) | `PATCH /{namespace}/brands/{id}` | `Brand.updated` | | [Brand.delete](/business/nouns/brand/delete?interface=api) | `DELETE /{namespace}/brands/{id}` | `Brand.deleted` | | [Brand.clear](/business/nouns/brand/clear?interface=api) | `POST /{namespace}/brands/{brand}/clear` | [`Brand.cleared`](/business/events/Brand.cleared) | ### Budget | Operation | Route | Event | | --- | --- | --- | | [Budget.create](/business/nouns/budget/create?interface=api) | `POST /{namespace}/budgets` | `Budget.created` | | [Budget.get](/business/nouns/budget/get?interface=api) | `GET /{namespace}/budgets/{id}` | None. | | [Budget.list](/business/nouns/budget/list?interface=api) | `GET /{namespace}/budgets` | None. | | [Budget.update](/business/nouns/budget/update?interface=api) | `PATCH /{namespace}/budgets/{id}` | `Budget.updated` | | [Budget.delete](/business/nouns/budget/delete?interface=api) | `DELETE /{namespace}/budgets/{id}` | `Budget.deleted` | ### Builder | Operation | Route | Event | | --- | --- | --- | | [Builder.get](/business/nouns/builder/get?interface=api) | `GET /{namespace}/builders/{id}` | None. | | [Builder.list](/business/nouns/builder/list?interface=api) | `GET /{namespace}/builders` | None. | ### Campaign | Operation | Route | Event | | --- | --- | --- | | [Campaign.create](/business/nouns/campaign/create?interface=api) | `POST /{namespace}/campaigns` | `Campaign.created` | | [Campaign.get](/business/nouns/campaign/get?interface=api) | `GET /{namespace}/campaigns/{id}` | None. | | [Campaign.list](/business/nouns/campaign/list?interface=api) | `GET /{namespace}/campaigns` | None. | | [Campaign.update](/business/nouns/campaign/update?interface=api) | `PATCH /{namespace}/campaigns/{id}` | `Campaign.updated` | | [Campaign.delete](/business/nouns/campaign/delete?interface=api) | `DELETE /{namespace}/campaigns/{id}` | `Campaign.deleted` | ### Candidate | Operation | Route | Event | | --- | --- | --- | | [Candidate.create](/business/nouns/candidate/create?interface=api) | `POST /{namespace}/candidates` | `Candidate.created` | | [Candidate.get](/business/nouns/candidate/get?interface=api) | `GET /{namespace}/candidates/{id}` | None. | | [Candidate.list](/business/nouns/candidate/list?interface=api) | `GET /{namespace}/candidates` | None. | | [Candidate.update](/business/nouns/candidate/update?interface=api) | `PATCH /{namespace}/candidates/{id}` | `Candidate.updated` | | [Candidate.delete](/business/nouns/candidate/delete?interface=api) | `DELETE /{namespace}/candidates/{id}` | `Candidate.deleted` | | [Candidate.screen](/business/nouns/candidate/screen?interface=api) | `POST /{namespace}/candidates/{candidate}/screen` | [`Candidate.screened`](/business/events/Candidate.screened) | ### Capability | Operation | Route | Event | | --- | --- | --- | | [Capability.get](/business/nouns/capability/get?interface=api) | `GET /{namespace}/capabilities/{id}` | None. | | [Capability.list](/business/nouns/capability/list?interface=api) | `GET /{namespace}/capabilities` | None. | ### Capital Call | Operation | Route | Event | | --- | --- | --- | | CapitalCall.get | `GET /{namespace}/capital-calls/{id}` | None. | | CapitalCall.list | `GET /{namespace}/capital-calls` | None. | ### Capital Commitment | Operation | Route | Event | | --- | --- | --- | | CapitalCommitment.create | `POST /{namespace}/capital-commitments` | `CapitalCommitment.created` | | CapitalCommitment.get | `GET /{namespace}/capital-commitments/{id}` | None. | | CapitalCommitment.list | `GET /{namespace}/capital-commitments` | None. | | CapitalCommitment.update | `PATCH /{namespace}/capital-commitments/{id}` | `CapitalCommitment.updated` | | CapitalCommitment.countersign | `POST /{namespace}/capital-commitments/{commitment}/countersign` | `CapitalCommitment.countersigned` | ### Card | Operation | Route | Event | | --- | --- | --- | | [Card.get](/business/nouns/card/get?interface=api) | `GET /{namespace}/cards/{id}` | None. | | [Card.list](/business/nouns/card/list?interface=api) | `GET /{namespace}/cards` | None. | | [Card.issue](/business/nouns/card/issue?interface=api) | `POST /{namespace}/cards/issue` | [`Card.issued`](/business/events/Card.issued) | ### Change | Operation | Route | Event | | --- | --- | --- | | [Change.create](/business/nouns/change/create?interface=api) | `POST /{namespace}/changes` | `Change.created` | | [Change.get](/business/nouns/change/get?interface=api) | `GET /{namespace}/changes/{id}` | None. | | [Change.list](/business/nouns/change/list?interface=api) | `GET /{namespace}/changes` | None. | | [Change.merge](/business/nouns/change/merge?interface=api) | `POST /{namespace}/changes/{change}/merge` | [`Change.merged`](/business/events/Change.merged) | | [Change.revert](/business/nouns/change/revert?interface=api) | `POST /{namespace}/changes/{change}/revert` | [`Change.reverted`](/business/events/Change.reverted) | | [Change.review](/business/nouns/change/review?interface=api) | `POST /{namespace}/changes/{change}/review` | [`Change.reviewed`](/business/events/Change.reviewed) | ### Channel | Operation | Route | Event | | --- | --- | --- | | [Channel.create](/business/nouns/channel/create?interface=api) | `POST /{namespace}/channels` | `Channel.created` | | [Channel.get](/business/nouns/channel/get?interface=api) | `GET /{namespace}/channels/{id}` | None. | | [Channel.list](/business/nouns/channel/list?interface=api) | `GET /{namespace}/channels` | None. | | [Channel.update](/business/nouns/channel/update?interface=api) | `PATCH /{namespace}/channels/{id}` | `Channel.updated` | | [Channel.delete](/business/nouns/channel/delete?interface=api) | `DELETE /{namespace}/channels/{id}` | `Channel.deleted` | ### Cohort | Operation | Route | Event | | --- | --- | --- | | [Cohort.create](/business/nouns/cohort/create?interface=api) | `POST /{namespace}/cohorts` | `Cohort.created` | | [Cohort.get](/business/nouns/cohort/get?interface=api) | `GET /{namespace}/cohorts/{id}` | None. | | [Cohort.list](/business/nouns/cohort/list?interface=api) | `GET /{namespace}/cohorts` | None. | | [Cohort.update](/business/nouns/cohort/update?interface=api) | `PATCH /{namespace}/cohorts/{id}` | `Cohort.updated` | | [Cohort.delete](/business/nouns/cohort/delete?interface=api) | `DELETE /{namespace}/cohorts/{id}` | `Cohort.deleted` | ### Collection | Operation | Route | Event | | --- | --- | --- | | [Collection.create](/business/nouns/collection/create?interface=api) | `POST /{namespace}/collections` | `Collection.created` | | [Collection.get](/business/nouns/collection/get?interface=api) | `GET /{namespace}/collections/{id}` | None. | | [Collection.list](/business/nouns/collection/list?interface=api) | `GET /{namespace}/collections` | None. | | [Collection.update](/business/nouns/collection/update?interface=api) | `PATCH /{namespace}/collections/{id}` | `Collection.updated` | | [Collection.delete](/business/nouns/collection/delete?interface=api) | `DELETE /{namespace}/collections/{id}` | `Collection.deleted` | | [Collection.export](/business/nouns/collection/export?interface=api) | `POST /{namespace}/collections/{collection}/export` | [`Collection.exported`](/business/events/Collection.exported) | | [Collection.query](/business/nouns/collection/query?interface=api) | `POST /{namespace}/collections/query` | [`Collection.queried`](/business/events/Collection.queried) | ### Comment | Operation | Route | Event | | --- | --- | --- | | [Comment.create](/business/nouns/comment/create?interface=api) | `POST /{namespace}/comments` | `Comment.created` | | [Comment.get](/business/nouns/comment/get?interface=api) | `GET /{namespace}/comments/{id}` | None. | | [Comment.list](/business/nouns/comment/list?interface=api) | `GET /{namespace}/comments` | None. | | [Comment.update](/business/nouns/comment/update?interface=api) | `PATCH /{namespace}/comments/{id}` | `Comment.updated` | | [Comment.delete](/business/nouns/comment/delete?interface=api) | `DELETE /{namespace}/comments/{id}` | `Comment.deleted` | ### Commission | Operation | Route | Event | | --- | --- | --- | | [Commission.create](/business/nouns/commission/create?interface=api) | `POST /{namespace}/commissions` | `Commission.created` | | [Commission.get](/business/nouns/commission/get?interface=api) | `GET /{namespace}/commissions/{id}` | None. | | [Commission.list](/business/nouns/commission/list?interface=api) | `GET /{namespace}/commissions` | None. | | [Commission.update](/business/nouns/commission/update?interface=api) | `PATCH /{namespace}/commissions/{id}` | `Commission.updated` | | [Commission.pay](/business/nouns/commission/pay?interface=api) | `POST /{namespace}/commissions/{commission}/pay` | [`Commission.paid`](/business/events/Commission.paid) | ### Company | Operation | Route | Event | | --- | --- | --- | | [Company.create](/business/nouns/company/create?interface=api) | `POST /{namespace}/companies` | `Company.created` | | [Company.get](/business/nouns/company/get?interface=api) | `GET /{namespace}/companies/{id}` | None. | | [Company.list](/business/nouns/company/list?interface=api) | `GET /{namespace}/companies` | None. | | [Company.update](/business/nouns/company/update?interface=api) | `PATCH /{namespace}/companies/{id}` | `Company.updated` | | [Company.dissolve](/business/nouns/company/dissolve?interface=api) | `POST /{namespace}/companies/{company}/dissolve` | [`Company.dissolved`](/business/events/Company.dissolved) | | [Company.incorporate](/business/nouns/company/incorporate?interface=api) | `POST /{namespace}/companies/incorporate` | [`Company.incorporated`](/business/events/Company.incorporated) | | [Company.register](/business/nouns/company/register?interface=api) | `POST /{namespace}/companies/register` | [`Company.registered`](/business/events/Company.registered) | | [Company.submit](/business/nouns/company/submit?interface=api) | `POST /{namespace}/companies/submit` | [`Company.submitted`](/business/events/Company.submitted) | ### Component | Operation | Route | Event | | --- | --- | --- | | [Component.create](/business/nouns/component/create?interface=api) | `POST /{namespace}/components` | `Component.created` | | [Component.get](/business/nouns/component/get?interface=api) | `GET /{namespace}/components/{id}` | None. | | [Component.list](/business/nouns/component/list?interface=api) | `GET /{namespace}/components` | None. | | [Component.update](/business/nouns/component/update?interface=api) | `PATCH /{namespace}/components/{id}` | `Component.updated` | | [Component.delete](/business/nouns/component/delete?interface=api) | `DELETE /{namespace}/components/{id}` | `Component.deleted` | ### Consent | Operation | Route | Event | | --- | --- | --- | | [Consent.create](/business/nouns/consent/create?interface=api) | `POST /{namespace}/consents` | `Consent.created` | | [Consent.get](/business/nouns/consent/get?interface=api) | `GET /{namespace}/consents/{id}` | None. | | [Consent.list](/business/nouns/consent/list?interface=api) | `GET /{namespace}/consents` | None. | | [Consent.update](/business/nouns/consent/update?interface=api) | `PATCH /{namespace}/consents/{id}` | `Consent.updated` | | [Consent.withdraw](/business/nouns/consent/withdraw?interface=api) | `POST /{namespace}/consents/{consent}/withdraw` | [`Consent.withdrawn`](/business/events/Consent.withdrawn) | ### Contact | Operation | Route | Event | | --- | --- | --- | | [Contact.create](/business/nouns/contact/create?interface=api) | `POST /{namespace}/contacts` | `Contact.created` | | [Contact.get](/business/nouns/contact/get?interface=api) | `GET /{namespace}/contacts/{id}` | None. | | [Contact.list](/business/nouns/contact/list?interface=api) | `GET /{namespace}/contacts` | None. | | [Contact.update](/business/nouns/contact/update?interface=api) | `PATCH /{namespace}/contacts/{id}` | `Contact.updated` | | [Contact.delete](/business/nouns/contact/delete?interface=api) | `DELETE /{namespace}/contacts/{id}` | `Contact.deleted` | | [Contact.enrich](/business/nouns/contact/enrich?interface=api) | `POST /{namespace}/contacts/{contact}/enrich` | [`Contact.enriched`](/business/events/Contact.enriched) | | [Contact.enroll](/business/nouns/contact/enroll?interface=api) | `POST /{namespace}/contacts/{contact}/enroll` | [`Contact.enrolled`](/business/events/Contact.enrolled) | | [Contact.merge](/business/nouns/contact/merge?interface=api) | `POST /{namespace}/contacts/{contact}/merge` | [`Contact.merged`](/business/events/Contact.merged) | | [Contact.subscribe](/business/nouns/contact/subscribe?interface=api) | `POST /{namespace}/contacts/{contact}/subscribe` | [`Contact.subscribed`](/business/events/Contact.subscribed) | | [Contact.suppress](/business/nouns/contact/suppress?interface=api) | `POST /{namespace}/contacts/{contact}/suppress` | [`Contact.suppressed`](/business/events/Contact.suppressed) | | [Contact.unsubscribe](/business/nouns/contact/unsubscribe?interface=api) | `POST /{namespace}/contacts/{contact}/unsubscribe` | [`Contact.unsubscribed`](/business/events/Contact.unsubscribed) | ### Content | Operation | Route | Event | | --- | --- | --- | | [Content.create](/business/nouns/content/create?interface=api) | `POST /{namespace}/content` | `Content.created` | | [Content.get](/business/nouns/content/get?interface=api) | `GET /{namespace}/content/{id}` | None. | | [Content.list](/business/nouns/content/list?interface=api) | `GET /{namespace}/content` | None. | | [Content.update](/business/nouns/content/update?interface=api) | `PATCH /{namespace}/content/{id}` | `Content.updated` | | [Content.delete](/business/nouns/content/delete?interface=api) | `DELETE /{namespace}/content/{id}` | `Content.deleted` | | [Content.draft](/business/nouns/content/draft?interface=api) | `POST /{namespace}/content/draft` | [`Content.drafted`](/business/events/Content.drafted) | | [Content.publish](/business/nouns/content/publish?interface=api) | `POST /{namespace}/content/{content}/publish` | [`Content.published`](/business/events/Content.published) | ### Control | Operation | Route | Event | | --- | --- | --- | | [Control.get](/business/nouns/control/get?interface=api) | `GET /{namespace}/controls/{id}` | None. | | [Control.list](/business/nouns/control/list?interface=api) | `GET /{namespace}/controls` | None. | ### Conversation | Operation | Route | Event | | --- | --- | --- | | [Conversation.create](/business/nouns/conversation/create?interface=api) | `POST /{namespace}/conversations` | `Conversation.created` | | [Conversation.get](/business/nouns/conversation/get?interface=api) | `GET /{namespace}/conversations/{id}` | None. | | [Conversation.list](/business/nouns/conversation/list?interface=api) | `GET /{namespace}/conversations` | None. | | [Conversation.update](/business/nouns/conversation/update?interface=api) | `PATCH /{namespace}/conversations/{id}` | `Conversation.updated` | | [Conversation.delete](/business/nouns/conversation/delete?interface=api) | `DELETE /{namespace}/conversations/{id}` | `Conversation.deleted` | | [Conversation.answer](/business/nouns/conversation/answer?interface=api) | `POST /{namespace}/conversations/{conversation}/answer` | [`Conversation.answered`](/business/events/Conversation.answered) | | [Conversation.assign](/business/nouns/conversation/assign?interface=api) | `POST /{namespace}/conversations/{conversation}/assign` | [`Conversation.assigned`](/business/events/Conversation.assigned) | | [Conversation.close](/business/nouns/conversation/close?interface=api) | `POST /{namespace}/conversations/{conversation}/close` | [`Conversation.closed`](/business/events/Conversation.closed) | | [Conversation.escalate](/business/nouns/conversation/escalate?interface=api) | `POST /{namespace}/conversations/{conversation}/escalate` | [`Conversation.escalated`](/business/events/Conversation.escalated) | | [Conversation.reopen](/business/nouns/conversation/reopen?interface=api) | `POST /{namespace}/conversations/{conversation}/reopen` | [`Conversation.reopened`](/business/events/Conversation.reopened) | ### Cost | Operation | Route | Event | | --- | --- | --- | | [Cost.get](/business/nouns/cost/get?interface=api) | `GET /{namespace}/costs/{id}` | None. | | [Cost.list](/business/nouns/cost/list?interface=api) | `GET /{namespace}/costs` | None. | ### Coupon | Operation | Route | Event | | --- | --- | --- | | [Coupon.create](/business/nouns/coupon/create?interface=api) | `POST /{namespace}/coupons` | `Coupon.created` | | [Coupon.get](/business/nouns/coupon/get?interface=api) | `GET /{namespace}/coupons/{id}` | None. | | [Coupon.list](/business/nouns/coupon/list?interface=api) | `GET /{namespace}/coupons` | None. | | [Coupon.update](/business/nouns/coupon/update?interface=api) | `PATCH /{namespace}/coupons/{id}` | `Coupon.updated` | ### Credential | Operation | Route | Event | | --- | --- | --- | | [Credential.create](/business/nouns/credential/create?interface=api) | `POST /{namespace}/credentials` | `Credential.created` | | [Credential.get](/business/nouns/credential/get?interface=api) | `GET /{namespace}/credentials/{id}` | None. | | [Credential.list](/business/nouns/credential/list?interface=api) | `GET /{namespace}/credentials` | None. | | [Credential.update](/business/nouns/credential/update?interface=api) | `PATCH /{namespace}/credentials/{id}` | `Credential.updated` | | [Credential.delete](/business/nouns/credential/delete?interface=api) | `DELETE /{namespace}/credentials/{id}` | `Credential.deleted` | | [Credential.verify](/business/nouns/credential/verify?interface=api) | `POST /{namespace}/credentials/{credential}/verify` | [`Credential.verified`](/business/events/Credential.verified) | ### Credit Grant | Operation | Route | Event | | --- | --- | --- | | [CreditGrant.create](/business/nouns/credit-grant/create?interface=api) | `POST /{namespace}/credit-grants` | `CreditGrant.created` | | [CreditGrant.get](/business/nouns/credit-grant/get?interface=api) | `GET /{namespace}/credit-grants/{id}` | None. | | [CreditGrant.list](/business/nouns/credit-grant/list?interface=api) | `GET /{namespace}/credit-grants` | None. | | [CreditGrant.apply](/business/nouns/credit-grant/apply?interface=api) | `POST /{namespace}/credit-grants/apply` | [`CreditGrant.applied`](/business/events/CreditGrant.applied) | | [CreditGrant.issue](/business/nouns/credit-grant/issue?interface=api) | `POST /{namespace}/credit-grants/issue` | [`CreditGrant.issued`](/business/events/CreditGrant.issued) | | [CreditGrant.void](/business/nouns/credit-grant/void?interface=api) | `POST /{namespace}/credit-grants/{creditGrant}/void` | [`CreditGrant.voided`](/business/events/CreditGrant.voided) | ### Criterion | Operation | Route | Event | | --- | --- | --- | | [Criterion.get](/business/nouns/criterion/get?interface=api) | `GET /{namespace}/criteria/{id}` | None. | | [Criterion.list](/business/nouns/criterion/list?interface=api) | `GET /{namespace}/criteria` | None. | ### Customer | Operation | Route | Event | | --- | --- | --- | | [Customer.create](/business/nouns/customer/create?interface=api) | `POST /{namespace}/customers` | `Customer.created` | | [Customer.get](/business/nouns/customer/get?interface=api) | `GET /{namespace}/customers/{id}` | None. | | [Customer.list](/business/nouns/customer/list?interface=api) | `GET /{namespace}/customers` | None. | | [Customer.update](/business/nouns/customer/update?interface=api) | `PATCH /{namespace}/customers/{id}` | `Customer.updated` | | [Customer.delete](/business/nouns/customer/delete?interface=api) | `DELETE /{namespace}/customers/{id}` | `Customer.deleted` | | [Customer.activate](/business/nouns/customer/activate?interface=api) | `POST /{namespace}/customers/{customer}/activate` | [`Customer.activated`](/business/events/Customer.activated) | | [Customer.exempt](/business/nouns/customer/exempt?interface=api) | `POST /{namespace}/customers/{customer}/exempt` | [`Customer.exempted`](/business/events/Customer.exempted) | ### Dashboard | Operation | Route | Event | | --- | --- | --- | | [Dashboard.create](/business/nouns/dashboard/create?interface=api) | `POST /{namespace}/dashboards` | `Dashboard.created` | | [Dashboard.get](/business/nouns/dashboard/get?interface=api) | `GET /{namespace}/dashboards/{id}` | None. | | [Dashboard.list](/business/nouns/dashboard/list?interface=api) | `GET /{namespace}/dashboards` | None. | | [Dashboard.update](/business/nouns/dashboard/update?interface=api) | `PATCH /{namespace}/dashboards/{id}` | `Dashboard.updated` | | [Dashboard.delete](/business/nouns/dashboard/delete?interface=api) | `DELETE /{namespace}/dashboards/{id}` | `Dashboard.deleted` | | [Dashboard.ask](/business/nouns/dashboard/ask?interface=api) | `POST /{namespace}/dashboards/ask` | [`Dashboard.asked`](/business/events/Dashboard.asked) | | [Dashboard.schedule](/business/nouns/dashboard/schedule?interface=api) | `POST /{namespace}/dashboards/{dashboard}/schedule` | [`Dashboard.scheduled`](/business/events/Dashboard.scheduled) | ### Dataset | Operation | Route | Event | | --- | --- | --- | | [Dataset.create](/business/nouns/dataset/create?interface=api) | `POST /{namespace}/datasets` | `Dataset.created` | | [Dataset.get](/business/nouns/dataset/get?interface=api) | `GET /{namespace}/datasets/{id}` | None. | | [Dataset.list](/business/nouns/dataset/list?interface=api) | `GET /{namespace}/datasets` | None. | | [Dataset.update](/business/nouns/dataset/update?interface=api) | `PATCH /{namespace}/datasets/{id}` | `Dataset.updated` | | [Dataset.delete](/business/nouns/dataset/delete?interface=api) | `DELETE /{namespace}/datasets/{id}` | `Dataset.deleted` | ### Deal | Operation | Route | Event | | --- | --- | --- | | [Deal.create](/business/nouns/deal/create?interface=api) | `POST /{namespace}/deals` | `Deal.created` | | [Deal.get](/business/nouns/deal/get?interface=api) | `GET /{namespace}/deals/{id}` | None. | | [Deal.list](/business/nouns/deal/list?interface=api) | `GET /{namespace}/deals` | None. | | [Deal.update](/business/nouns/deal/update?interface=api) | `PATCH /{namespace}/deals/{id}` | `Deal.updated` | | [Deal.delete](/business/nouns/deal/delete?interface=api) | `DELETE /{namespace}/deals/{id}` | `Deal.deleted` | | [Deal.advance](/business/nouns/deal/advance?interface=api) | `POST /{namespace}/deals/{deal}/advance` | [`Deal.advanced`](/business/events/Deal.advanced) | | [Deal.assign](/business/nouns/deal/assign?interface=api) | `POST /{namespace}/deals/{deal}/assign` | [`Deal.assigned`](/business/events/Deal.assigned) | | [Deal.lose](/business/nouns/deal/lose?interface=api) | `POST /{namespace}/deals/{deal}/lose` | [`Deal.lost`](/business/events/Deal.lost) | | [Deal.propose](/business/nouns/deal/propose?interface=api) | `POST /{namespace}/deals/{deal}/propose` | [`Deal.proposed`](/business/events/Deal.proposed) | | [Deal.win](/business/nouns/deal/win?interface=api) | `POST /{namespace}/deals/{deal}/win` | [`Deal.won`](/business/events/Deal.won) | ### Decision | Operation | Route | Event | | --- | --- | --- | | [Decision.create](/business/nouns/decision/create?interface=api) | `POST /{namespace}/decisions` | `Decision.created` | | [Decision.get](/business/nouns/decision/get?interface=api) | `GET /{namespace}/decisions/{id}` | None. | | [Decision.list](/business/nouns/decision/list?interface=api) | `GET /{namespace}/decisions` | None. | | [Decision.supersede](/business/nouns/decision/supersede?interface=api) | `POST /{namespace}/decisions/{decision}/supersede` | [`Decision.superseded`](/business/events/Decision.superseded) | ### Demand Budget | Operation | Route | Event | | --- | --- | --- | | [DemandBudget.create](/business/nouns/demand-budget/create?interface=api) | `POST /{namespace}/demand-budgets` | `DemandBudget.created` | | [DemandBudget.get](/business/nouns/demand-budget/get?interface=api) | `GET /{namespace}/demand-budgets/{id}` | None. | | [DemandBudget.list](/business/nouns/demand-budget/list?interface=api) | `GET /{namespace}/demand-budgets` | None. | | [DemandBudget.update](/business/nouns/demand-budget/update?interface=api) | `PATCH /{namespace}/demand-budgets/{id}` | `DemandBudget.updated` | ### Dispute | Operation | Route | Event | | --- | --- | --- | | [Dispute.get](/business/nouns/dispute/get?interface=api) | `GET /{namespace}/disputes/{id}` | None. | | [Dispute.list](/business/nouns/dispute/list?interface=api) | `GET /{namespace}/disputes` | None. | | [Dispute.accept](/business/nouns/dispute/accept?interface=api) | `POST /{namespace}/disputes/{dispute}/accept` | [`Dispute.accepted`](/business/events/Dispute.accepted) | | [Dispute.answer](/business/nouns/dispute/answer?interface=api) | `POST /{namespace}/disputes/{dispute}/answer` | [`Dispute.answered`](/business/events/Dispute.answered) | | [Dispute.appeal](/business/nouns/dispute/appeal?interface=api) | `POST /{namespace}/disputes/{dispute}/appeal` | [`Dispute.appealed`](/business/events/Dispute.appealed) | | [Dispute.decide](/business/nouns/dispute/decide?interface=api) | `POST /{namespace}/disputes/{dispute}/decide` | [`Dispute.decided`](/business/events/Dispute.decided) | ### DNS Record | Operation | Route | Event | | --- | --- | --- | | [DNSRecord.get](/business/nouns/dns-record/get?interface=api) | `GET /{namespace}/dns-records/{id}` | None. | | [DNSRecord.list](/business/nouns/dns-record/list?interface=api) | `GET /{namespace}/dns-records` | None. | | [DNSRecord.remove](/business/nouns/dns-record/remove?interface=api) | `POST /{namespace}/dns-records/{record}/remove` | [`DNSRecord.removed`](/business/events/DNSRecord.removed) | | [DNSRecord.set](/business/nouns/dns-record/set?interface=api) | `POST /{namespace}/dns-records/set` | [`DNSRecord.set`](/business/events/DNSRecord.set) | ### Document | Operation | Route | Event | | --- | --- | --- | | [Document.create](/business/nouns/document/create?interface=api) | `POST /{namespace}/documents` | `Document.created` | | [Document.get](/business/nouns/document/get?interface=api) | `GET /{namespace}/documents/{id}` | None. | | [Document.list](/business/nouns/document/list?interface=api) | `GET /{namespace}/documents` | None. | | [Document.update](/business/nouns/document/update?interface=api) | `PATCH /{namespace}/documents/{id}` | `Document.updated` | | [Document.delete](/business/nouns/document/delete?interface=api) | `DELETE /{namespace}/documents/{id}` | `Document.deleted` | | [Document.render](/business/nouns/document/render?interface=api) | `POST /{namespace}/documents/{document}/render` | [`Document.rendered`](/business/events/Document.rendered) | ### Domain | Operation | Route | Event | | --- | --- | --- | | [Domain.create](/business/nouns/domain/create?interface=api) | `POST /{namespace}/domains` | `Domain.created` | | [Domain.get](/business/nouns/domain/get?interface=api) | `GET /{namespace}/domains/{id}` | None. | | [Domain.list](/business/nouns/domain/list?interface=api) | `GET /{namespace}/domains` | None. | | [Domain.update](/business/nouns/domain/update?interface=api) | `PATCH /{namespace}/domains/{id}` | `Domain.updated` | | [Domain.delete](/business/nouns/domain/delete?interface=api) | `DELETE /{namespace}/domains/{id}` | `Domain.deleted` | | [Domain.authenticate](/business/nouns/domain/authenticate?interface=api) | `POST /{namespace}/domains/{domain}/authenticate` | [`Domain.authenticated`](/business/events/Domain.authenticated) | | [Domain.benchmark](/business/nouns/domain/benchmark?interface=api) | `POST /{namespace}/domains/benchmark` | [`Domain.benchmarked`](/business/events/Domain.benchmarked) | | [Domain.claim](/business/nouns/domain/claim?interface=api) | `POST /{namespace}/domains/claim` | [`Domain.claimed`](/business/events/Domain.claimed) | | [Domain.connect](/business/nouns/domain/connect?interface=api) | `POST /{namespace}/domains/connect` | [`Domain.connected`](/business/events/Domain.connected) | | [Domain.register](/business/nouns/domain/register?interface=api) | `POST /{namespace}/domains/register` | [`Domain.registered`](/business/events/Domain.registered) | | [Domain.release](/business/nouns/domain/release?interface=api) | `POST /{namespace}/domains/{domain}/release` | [`Domain.released`](/business/events/Domain.released) | | [Domain.renew](/business/nouns/domain/renew?interface=api) | `POST /{namespace}/domains/{domain}/renew` | [`Domain.renewed`](/business/events/Domain.renewed) | | [Domain.search](/business/nouns/domain/search?interface=api) | `POST /{namespace}/domains/search` | [`Domain.searched`](/business/events/Domain.searched) | | [Domain.transfer](/business/nouns/domain/transfer?interface=api) | `POST /{namespace}/domains/{domain}/transfer` | [`Domain.transferred`](/business/events/Domain.transferred) | | [Domain.verify](/business/nouns/domain/verify?interface=api) | `POST /{namespace}/domains/{domain}/verify` | [`Domain.verified`](/business/events/Domain.verified) | ### Enrollment | Operation | Route | Event | | --- | --- | --- | | [Enrollment.create](/business/nouns/enrollment/create?interface=api) | `POST /{namespace}/enrollments` | `Enrollment.created` | | [Enrollment.get](/business/nouns/enrollment/get?interface=api) | `GET /{namespace}/enrollments/{id}` | None. | | [Enrollment.list](/business/nouns/enrollment/list?interface=api) | `GET /{namespace}/enrollments` | None. | | [Enrollment.update](/business/nouns/enrollment/update?interface=api) | `PATCH /{namespace}/enrollments/{id}` | `Enrollment.updated` | | [Enrollment.delete](/business/nouns/enrollment/delete?interface=api) | `DELETE /{namespace}/enrollments/{id}` | `Enrollment.deleted` | | [Enrollment.cancel](/business/nouns/enrollment/cancel?interface=api) | `POST /{namespace}/enrollments/{enrollment}/cancel` | [`Enrollment.canceled`](/business/events/Enrollment.canceled) | | [Enrollment.pause](/business/nouns/enrollment/pause?interface=api) | `POST /{namespace}/enrollments/{enrollment}/pause` | [`Enrollment.paused`](/business/events/Enrollment.paused) | | [Enrollment.resume](/business/nouns/enrollment/resume?interface=api) | `POST /{namespace}/enrollments/{enrollment}/resume` | [`Enrollment.resumed`](/business/events/Enrollment.resumed) | ### Entitlement | Operation | Route | Event | | --- | --- | --- | | [Entitlement.create](/business/nouns/entitlement/create?interface=api) | `POST /{namespace}/entitlements` | `Entitlement.created` | | [Entitlement.get](/business/nouns/entitlement/get?interface=api) | `GET /{namespace}/entitlements/{id}` | None. | | [Entitlement.list](/business/nouns/entitlement/list?interface=api) | `GET /{namespace}/entitlements` | None. | | [Entitlement.update](/business/nouns/entitlement/update?interface=api) | `PATCH /{namespace}/entitlements/{id}` | `Entitlement.updated` | | [Entitlement.delete](/business/nouns/entitlement/delete?interface=api) | `DELETE /{namespace}/entitlements/{id}` | `Entitlement.deleted` | | [Entitlement.check](/business/nouns/entitlement/check?interface=api) | `POST /{namespace}/entitlements/check` | [`Entitlement.checked`](/business/events/Entitlement.checked) | ### Entry | Operation | Route | Event | | --- | --- | --- | | [Entry.get](/business/nouns/entry/get?interface=api) | `GET /{namespace}/entries/{id}` | None. | | [Entry.list](/business/nouns/entry/list?interface=api) | `GET /{namespace}/entries` | None. | | [Entry.post](/business/nouns/entry/post?interface=api) | `POST /{namespace}/entries/post` | [`Entry.posted`](/business/events/Entry.posted) | | [Entry.settle](/business/nouns/entry/settle?interface=api) | `POST /{namespace}/entries/settle` | [`Entry.settled`](/business/events/Entry.settled) | ### Evaluator | Operation | Route | Event | | --- | --- | --- | | [Evaluator.create](/business/nouns/evaluator/create?interface=api) | `POST /{namespace}/evaluators` | `Evaluator.created` | | [Evaluator.get](/business/nouns/evaluator/get?interface=api) | `GET /{namespace}/evaluators/{id}` | None. | | [Evaluator.list](/business/nouns/evaluator/list?interface=api) | `GET /{namespace}/evaluators` | None. | | [Evaluator.update](/business/nouns/evaluator/update?interface=api) | `PATCH /{namespace}/evaluators/{id}` | `Evaluator.updated` | | [Evaluator.delete](/business/nouns/evaluator/delete?interface=api) | `DELETE /{namespace}/evaluators/{id}` | `Evaluator.deleted` | ### Event | Operation | Route | Event | | --- | --- | --- | | [Event.create](/business/nouns/event/create?interface=api) | `POST /{namespace}/events` | `Event.created` | | [Event.get](/business/nouns/event/get?interface=api) | `GET /{namespace}/events/{id}` | None. | | [Event.list](/business/nouns/event/list?interface=api) | `GET /{namespace}/events` | None. | | [Event.capture](/business/nouns/event/capture?interface=api) | `POST /{namespace}/events/capture` | [`Event.captured`](/business/events/Event.captured) | ### Evidence | Operation | Route | Event | | --- | --- | --- | | [Evidence.create](/business/nouns/evidence/create?interface=api) | `POST /{namespace}/evidence` | `Evidence.created` | | [Evidence.get](/business/nouns/evidence/get?interface=api) | `GET /{namespace}/evidence/{id}` | None. | | [Evidence.list](/business/nouns/evidence/list?interface=api) | `GET /{namespace}/evidence` | None. | ### Experiment | Operation | Route | Event | | --- | --- | --- | | [Experiment.create](/business/nouns/experiment/create?interface=api) | `POST /{namespace}/experiments` | `Experiment.created` | | [Experiment.get](/business/nouns/experiment/get?interface=api) | `GET /{namespace}/experiments/{id}` | None. | | [Experiment.list](/business/nouns/experiment/list?interface=api) | `GET /{namespace}/experiments` | None. | | [Experiment.conclude](/business/nouns/experiment/conclude?interface=api) | `POST /{namespace}/experiments/{experiment}/conclude` | [`Experiment.concluded`](/business/events/Experiment.concluded) | | [Experiment.start](/business/nouns/experiment/start?interface=api) | `POST /{namespace}/experiments/{experiment}/start` | [`Experiment.started`](/business/events/Experiment.started) | ### Exposure | Operation | Route | Event | | --- | --- | --- | | [Exposure.create](/business/nouns/exposure/create?interface=api) | `POST /{namespace}/exposures` | `Exposure.created` | | [Exposure.get](/business/nouns/exposure/get?interface=api) | `GET /{namespace}/exposures/{id}` | None. | | [Exposure.list](/business/nouns/exposure/list?interface=api) | `GET /{namespace}/exposures` | None. | ### File | Operation | Route | Event | | --- | --- | --- | | [File.create](/business/nouns/file/create?interface=api) | `POST /{namespace}/files` | `File.created` | | [File.get](/business/nouns/file/get?interface=api) | `GET /{namespace}/files/{id}` | None. | | [File.list](/business/nouns/file/list?interface=api) | `GET /{namespace}/files` | None. | | [File.update](/business/nouns/file/update?interface=api) | `PATCH /{namespace}/files/{id}` | `File.updated` | | [File.delete](/business/nouns/file/delete?interface=api) | `DELETE /{namespace}/files/{id}` | `File.deleted` | | [File.edit](/business/nouns/file/edit?interface=api) | `POST /{namespace}/files/{file}/edit` | [`File.edited`](/business/events/File.edited) | | [File.generate](/business/nouns/file/generate?interface=api) | `POST /{namespace}/files/generate` | [`File.generated`](/business/events/File.generated) | ### Flag | Operation | Route | Event | | --- | --- | --- | | [Flag.create](/business/nouns/flag/create?interface=api) | `POST /{namespace}/flags` | `Flag.created` | | [Flag.get](/business/nouns/flag/get?interface=api) | `GET /{namespace}/flags/{id}` | None. | | [Flag.list](/business/nouns/flag/list?interface=api) | `GET /{namespace}/flags` | None. | | [Flag.update](/business/nouns/flag/update?interface=api) | `PATCH /{namespace}/flags/{id}` | `Flag.updated` | | [Flag.delete](/business/nouns/flag/delete?interface=api) | `DELETE /{namespace}/flags/{id}` | `Flag.deleted` | | [Flag.evaluate](/business/nouns/flag/evaluate?interface=api) | `POST /{namespace}/flags/{flag}/evaluate` | [`Flag.evaluated`](/business/events/Flag.evaluated) | ### Flow | Operation | Route | Event | | --- | --- | --- | | [Flow.create](/business/nouns/flow/create?interface=api) | `POST /{namespace}/flows` | `Flow.created` | | [Flow.get](/business/nouns/flow/get?interface=api) | `GET /{namespace}/flows/{id}` | None. | | [Flow.list](/business/nouns/flow/list?interface=api) | `GET /{namespace}/flows` | None. | | [Flow.update](/business/nouns/flow/update?interface=api) | `PATCH /{namespace}/flows/{id}` | `Flow.updated` | | [Flow.delete](/business/nouns/flow/delete?interface=api) | `DELETE /{namespace}/flows/{id}` | `Flow.deleted` | ### Forecast | Operation | Route | Event | | --- | --- | --- | | [Forecast.create](/business/nouns/forecast/create?interface=api) | `POST /{namespace}/forecasts` | `Forecast.created` | | [Forecast.get](/business/nouns/forecast/get?interface=api) | `GET /{namespace}/forecasts/{id}` | None. | | [Forecast.list](/business/nouns/forecast/list?interface=api) | `GET /{namespace}/forecasts` | None. | ### Form | Operation | Route | Event | | --- | --- | --- | | [Form.create](/business/nouns/form/create?interface=api) | `POST /{namespace}/forms` | `Form.created` | | [Form.get](/business/nouns/form/get?interface=api) | `GET /{namespace}/forms/{id}` | None. | | [Form.list](/business/nouns/form/list?interface=api) | `GET /{namespace}/forms` | None. | | [Form.update](/business/nouns/form/update?interface=api) | `PATCH /{namespace}/forms/{id}` | `Form.updated` | | [Form.delete](/business/nouns/form/delete?interface=api) | `DELETE /{namespace}/forms/{id}` | `Form.deleted` | ### Function | Operation | Route | Event | | --- | --- | --- | | [Function.create](/business/nouns/function/create?interface=api) | `POST /{namespace}/functions` | `Function.created` | | [Function.get](/business/nouns/function/get?interface=api) | `GET /{namespace}/functions/{id}` | None. | | [Function.list](/business/nouns/function/list?interface=api) | `GET /{namespace}/functions` | None. | | [Function.update](/business/nouns/function/update?interface=api) | `PATCH /{namespace}/functions/{id}` | `Function.updated` | | [Function.delete](/business/nouns/function/delete?interface=api) | `DELETE /{namespace}/functions/{id}` | `Function.deleted` | ### Fund | Operation | Route | Event | | --- | --- | --- | | Fund.create | `POST /{namespace}/funds` | `Fund.created` | | Fund.get | `GET /{namespace}/funds/{id}` | None. | | Fund.list | `GET /{namespace}/funds` | None. | | Fund.update | `PATCH /{namespace}/funds/{id}` | `Fund.updated` | | Fund.delete | `DELETE /{namespace}/funds/{id}` | `Fund.deleted` | | Fund.call | `POST /{namespace}/funds/{fund}/call` | `Fund.called` | | Fund.distribute | `POST /{namespace}/funds/{fund}/distribute` | `Fund.distributed` | | Fund.report | `POST /{namespace}/funds/{fund}/report` | `Fund.reported` | ### Fund Distribution | Operation | Route | Event | | --- | --- | --- | | FundDistribution.get | `GET /{namespace}/fund-distributions/{id}` | None. | | FundDistribution.list | `GET /{namespace}/fund-distributions` | None. | ### Funnel | Operation | Route | Event | | --- | --- | --- | | [Funnel.create](/business/nouns/funnel/create?interface=api) | `POST /{namespace}/funnels` | `Funnel.created` | | [Funnel.get](/business/nouns/funnel/get?interface=api) | `GET /{namespace}/funnels/{id}` | None. | | [Funnel.list](/business/nouns/funnel/list?interface=api) | `GET /{namespace}/funnels` | None. | | [Funnel.update](/business/nouns/funnel/update?interface=api) | `PATCH /{namespace}/funnels/{id}` | `Funnel.updated` | | [Funnel.delete](/business/nouns/funnel/delete?interface=api) | `DELETE /{namespace}/funnels/{id}` | `Funnel.deleted` | ### Gathering | Operation | Route | Event | | --- | --- | --- | | [Gathering.create](/business/nouns/gathering/create?interface=api) | `POST /{namespace}/gatherings` | `Gathering.created` | | [Gathering.get](/business/nouns/gathering/get?interface=api) | `GET /{namespace}/gatherings/{id}` | None. | | [Gathering.list](/business/nouns/gathering/list?interface=api) | `GET /{namespace}/gatherings` | None. | | [Gathering.update](/business/nouns/gathering/update?interface=api) | `PATCH /{namespace}/gatherings/{id}` | `Gathering.updated` | | [Gathering.delete](/business/nouns/gathering/delete?interface=api) | `DELETE /{namespace}/gatherings/{id}` | `Gathering.deleted` | | [Gathering.register](/business/nouns/gathering/register?interface=api) | `POST /{namespace}/gatherings/{gathering}/register` | [`Gathering.registered`](/business/events/Gathering.registered) | ### Goal | Operation | Route | Event | | --- | --- | --- | | [Goal.create](/business/nouns/goal/create?interface=api) | `POST /{namespace}/goals` | `Goal.created` | | [Goal.get](/business/nouns/goal/get?interface=api) | `GET /{namespace}/goals/{id}` | None. | | [Goal.list](/business/nouns/goal/list?interface=api) | `GET /{namespace}/goals` | None. | | [Goal.update](/business/nouns/goal/update?interface=api) | `PATCH /{namespace}/goals/{id}` | `Goal.updated` | | [Goal.delete](/business/nouns/goal/delete?interface=api) | `DELETE /{namespace}/goals/{id}` | `Goal.deleted` | ### Guard | Operation | Route | Event | | --- | --- | --- | | [Guard.create](/business/nouns/guard/create?interface=api) | `POST /{namespace}/guards` | `Guard.created` | | [Guard.get](/business/nouns/guard/get?interface=api) | `GET /{namespace}/guards/{id}` | None. | | [Guard.list](/business/nouns/guard/list?interface=api) | `GET /{namespace}/guards` | None. | | [Guard.update](/business/nouns/guard/update?interface=api) | `PATCH /{namespace}/guards/{id}` | `Guard.updated` | | [Guard.delete](/business/nouns/guard/delete?interface=api) | `DELETE /{namespace}/guards/{id}` | `Guard.deleted` | ### Handle | Operation | Route | Event | | --- | --- | --- | | [Handle.create](/business/nouns/handle/create?interface=api) | `POST /{namespace}/handles` | `Handle.created` | | [Handle.get](/business/nouns/handle/get?interface=api) | `GET /{namespace}/handles/{id}` | None. | | [Handle.list](/business/nouns/handle/list?interface=api) | `GET /{namespace}/handles` | None. | | [Handle.update](/business/nouns/handle/update?interface=api) | `PATCH /{namespace}/handles/{id}` | `Handle.updated` | | [Handle.connect](/business/nouns/handle/connect?interface=api) | `POST /{namespace}/handles/{handle}/connect` | [`Handle.connected`](/business/events/Handle.connected) | ### Holder | Operation | Route | Event | | --- | --- | --- | | [Holder.create](/business/nouns/holder/create?interface=api) | `POST /{namespace}/holders` | `Holder.created` | | [Holder.get](/business/nouns/holder/get?interface=api) | `GET /{namespace}/holders/{id}` | None. | | [Holder.list](/business/nouns/holder/list?interface=api) | `GET /{namespace}/holders` | None. | | [Holder.update](/business/nouns/holder/update?interface=api) | `PATCH /{namespace}/holders/{id}` | `Holder.updated` | ### Human | Operation | Route | Event | | --- | --- | --- | | [Human.create](/business/nouns/human/create?interface=api) | `POST /{namespace}/humans` | `Human.created` | | [Human.get](/business/nouns/human/get?interface=api) | `GET /{namespace}/humans/{id}` | None. | | [Human.list](/business/nouns/human/list?interface=api) | `GET /{namespace}/humans` | None. | | [Human.update](/business/nouns/human/update?interface=api) | `PATCH /{namespace}/humans/{id}` | `Human.updated` | | [Human.delete](/business/nouns/human/delete?interface=api) | `DELETE /{namespace}/humans/{id}` | `Human.deleted` | | [Human.hold](/business/nouns/human/hold?interface=api) | `POST /{namespace}/humans/{human}/hold` | [`Human.held`](/business/events/Human.held) | | [Human.invite](/business/nouns/human/invite?interface=api) | `POST /{namespace}/humans/invite` | [`Human.invited`](/business/events/Human.invited) | | [Human.onboard](/business/nouns/human/onboard?interface=api) | `POST /{namespace}/humans/{human}/onboard` | [`Human.onboarded`](/business/events/Human.onboarded) | | [Human.recruit](/business/nouns/human/recruit?interface=api) | `POST /{namespace}/humans/recruit` | [`Human.recruited`](/business/events/Human.recruited) | | [Human.release](/business/nouns/human/release?interface=api) | `POST /{namespace}/humans/{human}/release` | [`Human.released`](/business/events/Human.released) | | [Human.remit](/business/nouns/human/remit?interface=api) | `POST /{namespace}/humans/{human}/remit` | [`Human.remitted`](/business/events/Human.remitted) | | [Human.suspend](/business/nouns/human/suspend?interface=api) | `POST /{namespace}/humans/{human}/suspend` | [`Human.suspended`](/business/events/Human.suspended) | ### Hypothesis | Operation | Route | Event | | --- | --- | --- | | [Hypothesis.create](/business/nouns/hypothesis/create?interface=api) | `POST /{namespace}/hypotheses` | `Hypothesis.created` | | [Hypothesis.get](/business/nouns/hypothesis/get?interface=api) | `GET /{namespace}/hypotheses/{id}` | None. | | [Hypothesis.list](/business/nouns/hypothesis/list?interface=api) | `GET /{namespace}/hypotheses` | None. | | [Hypothesis.drop](/business/nouns/hypothesis/drop?interface=api) | `POST /{namespace}/hypotheses/{hypothesis}/drop` | [`Hypothesis.dropped`](/business/events/Hypothesis.dropped) | | [Hypothesis.test](/business/nouns/hypothesis/test?interface=api) | `POST /{namespace}/hypotheses/{hypothesis}/test` | [`Hypothesis.tested`](/business/events/Hypothesis.tested) | ### ICP | Operation | Route | Event | | --- | --- | --- | | [ICP.create](/business/nouns/icp/create?interface=api) | `POST /{namespace}/icps` | `ICP.created` | | [ICP.get](/business/nouns/icp/get?interface=api) | `GET /{namespace}/icps/{id}` | None. | | [ICP.list](/business/nouns/icp/list?interface=api) | `GET /{namespace}/icps` | None. | | [ICP.update](/business/nouns/icp/update?interface=api) | `PATCH /{namespace}/icps/{id}` | `ICP.updated` | | [ICP.delete](/business/nouns/icp/delete?interface=api) | `DELETE /{namespace}/icps/{id}` | `ICP.deleted` | ### Idea | Operation | Route | Event | | --- | --- | --- | | [Idea.create](/business/nouns/idea/create?interface=api) | `POST /{namespace}/ideas` | `Idea.created` | | [Idea.get](/business/nouns/idea/get?interface=api) | `GET /{namespace}/ideas/{id}` | None. | | [Idea.list](/business/nouns/idea/list?interface=api) | `GET /{namespace}/ideas` | None. | | [Idea.pursue](/business/nouns/idea/pursue?interface=api) | `POST /{namespace}/ideas/{idea}/pursue` | [`Idea.pursued`](/business/events/Idea.pursued) | ### Implementation | Operation | Route | Event | | --- | --- | --- | | [Implementation.create](/business/nouns/implementation/create?interface=api) | `POST /{namespace}/implementations` | `Implementation.created` | | [Implementation.get](/business/nouns/implementation/get?interface=api) | `GET /{namespace}/implementations/{id}` | None. | | [Implementation.list](/business/nouns/implementation/list?interface=api) | `GET /{namespace}/implementations` | None. | | [Implementation.update](/business/nouns/implementation/update?interface=api) | `PATCH /{namespace}/implementations/{id}` | `Implementation.updated` | | [Implementation.delete](/business/nouns/implementation/delete?interface=api) | `DELETE /{namespace}/implementations/{id}` | `Implementation.deleted` | ### Incident | Operation | Route | Event | | --- | --- | --- | | [Incident.create](/business/nouns/incident/create?interface=api) | `POST /{namespace}/incidents` | `Incident.created` | | [Incident.get](/business/nouns/incident/get?interface=api) | `GET /{namespace}/incidents/{id}` | None. | | [Incident.list](/business/nouns/incident/list?interface=api) | `GET /{namespace}/incidents` | None. | | [Incident.update](/business/nouns/incident/update?interface=api) | `PATCH /{namespace}/incidents/{id}` | `Incident.updated` | | [Incident.delete](/business/nouns/incident/delete?interface=api) | `DELETE /{namespace}/incidents/{id}` | `Incident.deleted` | | [Incident.acknowledge](/business/nouns/incident/acknowledge?interface=api) | `POST /{namespace}/incidents/{incident}/acknowledge` | [`Incident.acknowledged`](/business/events/Incident.acknowledged) | | [Incident.open](/business/nouns/incident/open?interface=api) | `POST /{namespace}/incidents/open` | [`Incident.opened`](/business/events/Incident.opened) | | [Incident.resolve](/business/nouns/incident/resolve?interface=api) | `POST /{namespace}/incidents/{incident}/resolve` | [`Incident.resolved`](/business/events/Incident.resolved) | ### Instrument | Operation | Route | Event | | --- | --- | --- | | [Instrument.get](/business/nouns/instrument/get?interface=api) | `GET /{namespace}/instruments/{id}` | None. | | [Instrument.list](/business/nouns/instrument/list?interface=api) | `GET /{namespace}/instruments` | None. | | [Instrument.cancel](/business/nouns/instrument/cancel?interface=api) | `POST /{namespace}/instruments/{instrument}/cancel` | [`Instrument.canceled`](/business/events/Instrument.canceled) | | [Instrument.convert](/business/nouns/instrument/convert?interface=api) | `POST /{namespace}/instruments/{instrument}/convert` | [`Instrument.converted`](/business/events/Instrument.converted) | | [Instrument.exercise](/business/nouns/instrument/exercise?interface=api) | `POST /{namespace}/instruments/{instrument}/exercise` | [`Instrument.exercised`](/business/events/Instrument.exercised) | | [Instrument.grant](/business/nouns/instrument/grant?interface=api) | `POST /{namespace}/instruments/grant` | [`Instrument.granted`](/business/events/Instrument.granted) | ### Integration | Operation | Route | Event | | --- | --- | --- | | [Integration.create](/business/nouns/integration/create?interface=api) | `POST /{namespace}/integrations` | `Integration.created` | | [Integration.get](/business/nouns/integration/get?interface=api) | `GET /{namespace}/integrations/{id}` | None. | | [Integration.list](/business/nouns/integration/list?interface=api) | `GET /{namespace}/integrations` | None. | | [Integration.update](/business/nouns/integration/update?interface=api) | `PATCH /{namespace}/integrations/{id}` | `Integration.updated` | | [Integration.delete](/business/nouns/integration/delete?interface=api) | `DELETE /{namespace}/integrations/{id}` | `Integration.deleted` | | [Integration.call](/business/nouns/integration/call?interface=api) | `POST /{namespace}/integrations/{integration}/call` | [`Integration.called`](/business/events/Integration.called) | | [Integration.connect](/business/nouns/integration/connect?interface=api) | `POST /{namespace}/integrations/connect` | [`Integration.connected`](/business/events/Integration.connected) | | [Integration.pause](/business/nouns/integration/pause?interface=api) | `POST /{namespace}/integrations/{integration}/pause` | [`Integration.paused`](/business/events/Integration.paused) | | [Integration.reconnect](/business/nouns/integration/reconnect?interface=api) | `POST /{namespace}/integrations/{integration}/reconnect` | [`Integration.reconnected`](/business/events/Integration.reconnected) | | [Integration.refresh](/business/nouns/integration/refresh?interface=api) | `POST /{namespace}/integrations/{integration}/refresh` | [`Integration.refreshed`](/business/events/Integration.refreshed) | | [Integration.resume](/business/nouns/integration/resume?interface=api) | `POST /{namespace}/integrations/{integration}/resume` | [`Integration.resumed`](/business/events/Integration.resumed) | | [Integration.revoke](/business/nouns/integration/revoke?interface=api) | `POST /{namespace}/integrations/{integration}/revoke` | [`Integration.revoked`](/business/events/Integration.revoked) | | [Integration.sync](/business/nouns/integration/sync?interface=api) | `POST /{namespace}/integrations/{integration}/sync` | [`Integration.synced`](/business/events/Integration.synced) | ### Interface | Operation | Route | Event | | --- | --- | --- | | [Interface.create](/business/nouns/interface/create?interface=api) | `POST /{namespace}/interfaces` | `Interface.created` | | [Interface.get](/business/nouns/interface/get?interface=api) | `GET /{namespace}/interfaces/{id}` | None. | | [Interface.list](/business/nouns/interface/list?interface=api) | `GET /{namespace}/interfaces` | None. | | [Interface.update](/business/nouns/interface/update?interface=api) | `PATCH /{namespace}/interfaces/{id}` | `Interface.updated` | | [Interface.delete](/business/nouns/interface/delete?interface=api) | `DELETE /{namespace}/interfaces/{id}` | `Interface.deleted` | ### Interview | Operation | Route | Event | | --- | --- | --- | | [Interview.create](/business/nouns/interview/create?interface=api) | `POST /{namespace}/interviews` | `Interview.created` | | [Interview.get](/business/nouns/interview/get?interface=api) | `GET /{namespace}/interviews/{id}` | None. | | [Interview.list](/business/nouns/interview/list?interface=api) | `GET /{namespace}/interviews` | None. | ### Invoice | Operation | Route | Event | | --- | --- | --- | | [Invoice.create](/business/nouns/invoice/create?interface=api) | `POST /{namespace}/invoices` | `Invoice.created` | | [Invoice.get](/business/nouns/invoice/get?interface=api) | `GET /{namespace}/invoices/{id}` | None. | | [Invoice.list](/business/nouns/invoice/list?interface=api) | `GET /{namespace}/invoices` | None. | | [Invoice.update](/business/nouns/invoice/update?interface=api) | `PATCH /{namespace}/invoices/{id}` | `Invoice.updated` | | [Invoice.bill](/business/nouns/invoice/bill?interface=api) | `POST /{namespace}/invoices/{invoice}/bill` | [`Invoice.billed`](/business/events/Invoice.billed) | | [Invoice.collect](/business/nouns/invoice/collect?interface=api) | `POST /{namespace}/invoices/{invoice}/collect` | [`Invoice.collected`](/business/events/Invoice.collected) | | [Invoice.refund](/business/nouns/invoice/refund?interface=api) | `POST /{namespace}/invoices/{invoice}/refund` | [`Invoice.refunded`](/business/events/Invoice.refunded) | | [Invoice.void](/business/nouns/invoice/void?interface=api) | `POST /{namespace}/invoices/{invoice}/void` | [`Invoice.voided`](/business/events/Invoice.voided) | ### Issue | Operation | Route | Event | | --- | --- | --- | | [Issue.create](/business/nouns/issue/create?interface=api) | `POST /{namespace}/issues` | `Issue.created` | | [Issue.get](/business/nouns/issue/get?interface=api) | `GET /{namespace}/issues/{id}` | None. | | [Issue.list](/business/nouns/issue/list?interface=api) | `GET /{namespace}/issues` | None. | | [Issue.update](/business/nouns/issue/update?interface=api) | `PATCH /{namespace}/issues/{id}` | `Issue.updated` | | [Issue.delete](/business/nouns/issue/delete?interface=api) | `DELETE /{namespace}/issues/{id}` | `Issue.deleted` | | [Issue.estimate](/business/nouns/issue/estimate?interface=api) | `POST /{namespace}/issues/{issue}/estimate` | [`Issue.estimated`](/business/events/Issue.estimated) | | [Issue.reopen](/business/nouns/issue/reopen?interface=api) | `POST /{namespace}/issues/{issue}/reopen` | [`Issue.reopened`](/business/events/Issue.reopened) | | [Issue.resolve](/business/nouns/issue/resolve?interface=api) | `POST /{namespace}/issues/{issue}/resolve` | [`Issue.resolved`](/business/events/Issue.resolved) | | [Issue.schedule](/business/nouns/issue/schedule?interface=api) | `POST /{namespace}/issues/{issue}/schedule` | [`Issue.scheduled`](/business/events/Issue.scheduled) | | [Issue.triage](/business/nouns/issue/triage?interface=api) | `POST /{namespace}/issues/{issue}/triage` | [`Issue.triaged`](/business/events/Issue.triaged) | ### Key Result | Operation | Route | Event | | --- | --- | --- | | [KeyResult.create](/business/nouns/key-result/create?interface=api) | `POST /{namespace}/key-results` | `KeyResult.created` | | [KeyResult.get](/business/nouns/key-result/get?interface=api) | `GET /{namespace}/key-results/{id}` | None. | | [KeyResult.list](/business/nouns/key-result/list?interface=api) | `GET /{namespace}/key-results` | None. | | [KeyResult.update](/business/nouns/key-result/update?interface=api) | `PATCH /{namespace}/key-results/{id}` | `KeyResult.updated` | | [KeyResult.delete](/business/nouns/key-result/delete?interface=api) | `DELETE /{namespace}/key-results/{id}` | `KeyResult.deleted` | ### Keyword | Operation | Route | Event | | --- | --- | --- | | [Keyword.create](/business/nouns/keyword/create?interface=api) | `POST /{namespace}/keywords` | `Keyword.created` | | [Keyword.get](/business/nouns/keyword/get?interface=api) | `GET /{namespace}/keywords/{id}` | None. | | [Keyword.list](/business/nouns/keyword/list?interface=api) | `GET /{namespace}/keywords` | None. | | [Keyword.update](/business/nouns/keyword/update?interface=api) | `PATCH /{namespace}/keywords/{id}` | `Keyword.updated` | | [Keyword.delete](/business/nouns/keyword/delete?interface=api) | `DELETE /{namespace}/keywords/{id}` | `Keyword.deleted` | | [Keyword.measure](/business/nouns/keyword/measure?interface=api) | `POST /{namespace}/keywords/{keyword}/measure` | [`Keyword.measured`](/business/events/Keyword.measured) | ### Lead | Operation | Route | Event | | --- | --- | --- | | [Lead.create](/business/nouns/lead/create?interface=api) | `POST /{namespace}/leads` | `Lead.created` | | [Lead.get](/business/nouns/lead/get?interface=api) | `GET /{namespace}/leads/{id}` | None. | | [Lead.list](/business/nouns/lead/list?interface=api) | `GET /{namespace}/leads` | None. | | [Lead.update](/business/nouns/lead/update?interface=api) | `PATCH /{namespace}/leads/{id}` | `Lead.updated` | | [Lead.delete](/business/nouns/lead/delete?interface=api) | `DELETE /{namespace}/leads/{id}` | `Lead.deleted` | | [Lead.assign](/business/nouns/lead/assign?interface=api) | `POST /{namespace}/leads/{lead}/assign` | [`Lead.assigned`](/business/events/Lead.assigned) | | [Lead.convert](/business/nouns/lead/convert?interface=api) | `POST /{namespace}/leads/{lead}/convert` | [`Lead.converted`](/business/events/Lead.converted) | | [Lead.disqualify](/business/nouns/lead/disqualify?interface=api) | `POST /{namespace}/leads/{lead}/disqualify` | [`Lead.disqualified`](/business/events/Lead.disqualified) | | [Lead.nurture](/business/nouns/lead/nurture?interface=api) | `POST /{namespace}/leads/{lead}/nurture` | [`Lead.nurtured`](/business/events/Lead.nurtured) | | [Lead.qualify](/business/nouns/lead/qualify?interface=api) | `POST /{namespace}/leads/{lead}/qualify` | [`Lead.qualified`](/business/events/Lead.qualified) | ### Lifecycle | Operation | Route | Event | | --- | --- | --- | | [Lifecycle.get](/business/nouns/lifecycle/get?interface=api) | `GET /{namespace}/lifecycles/{id}` | None. | | [Lifecycle.list](/business/nouns/lifecycle/list?interface=api) | `GET /{namespace}/lifecycles` | None. | | [Lifecycle.update](/business/nouns/lifecycle/update?interface=api) | `PATCH /{namespace}/lifecycles/{id}` | `Lifecycle.updated` | ### Limit | Operation | Route | Event | | --- | --- | --- | | [Limit.create](/business/nouns/limit/create?interface=api) | `POST /{namespace}/limits` | `Limit.created` | | [Limit.get](/business/nouns/limit/get?interface=api) | `GET /{namespace}/limits/{id}` | None. | | [Limit.list](/business/nouns/limit/list?interface=api) | `GET /{namespace}/limits` | None. | | [Limit.update](/business/nouns/limit/update?interface=api) | `PATCH /{namespace}/limits/{id}` | `Limit.updated` | | [Limit.delete](/business/nouns/limit/delete?interface=api) | `DELETE /{namespace}/limits/{id}` | `Limit.deleted` | | [Limit.raise](/business/nouns/limit/raise?interface=api) | `POST /{namespace}/limits/{limit}/raise` | [`Limit.raised`](/business/events/Limit.raised) | ### Mailbox | Operation | Route | Event | | --- | --- | --- | | [Mailbox.create](/business/nouns/mailbox/create?interface=api) | `POST /{namespace}/mailboxes` | `Mailbox.created` | | [Mailbox.get](/business/nouns/mailbox/get?interface=api) | `GET /{namespace}/mailboxes/{id}` | None. | | [Mailbox.list](/business/nouns/mailbox/list?interface=api) | `GET /{namespace}/mailboxes` | None. | | [Mailbox.update](/business/nouns/mailbox/update?interface=api) | `PATCH /{namespace}/mailboxes/{id}` | `Mailbox.updated` | | [Mailbox.rest](/business/nouns/mailbox/rest?interface=api) | `POST /{namespace}/mailboxes/{mailbox}/rest` | [`Mailbox.rested`](/business/events/Mailbox.rested) | | [Mailbox.retire](/business/nouns/mailbox/retire?interface=api) | `POST /{namespace}/mailboxes/{mailbox}/retire` | [`Mailbox.retired`](/business/events/Mailbox.retired) | | [Mailbox.warm](/business/nouns/mailbox/warm?interface=api) | `POST /{namespace}/mailboxes/{mailbox}/warm` | [`Mailbox.warmed`](/business/events/Mailbox.warmed) | ### Mandate | Operation | Route | Event | | --- | --- | --- | | [Mandate.create](/business/nouns/mandate/create?interface=api) | `POST /{namespace}/mandates` | `Mandate.created` | | [Mandate.get](/business/nouns/mandate/get?interface=api) | `GET /{namespace}/mandates/{id}` | None. | | [Mandate.list](/business/nouns/mandate/list?interface=api) | `GET /{namespace}/mandates` | None. | | [Mandate.update](/business/nouns/mandate/update?interface=api) | `PATCH /{namespace}/mandates/{id}` | `Mandate.updated` | | [Mandate.delete](/business/nouns/mandate/delete?interface=api) | `DELETE /{namespace}/mandates/{id}` | `Mandate.deleted` | | [Mandate.authorize](/business/nouns/mandate/authorize?interface=api) | `POST /{namespace}/mandates/authorize` | [`Mandate.authorized`](/business/events/Mandate.authorized) | | [Mandate.pause](/business/nouns/mandate/pause?interface=api) | `POST /{namespace}/mandates/{mandate}/pause` | [`Mandate.paused`](/business/events/Mandate.paused) | | [Mandate.resume](/business/nouns/mandate/resume?interface=api) | `POST /{namespace}/mandates/{mandate}/resume` | [`Mandate.resumed`](/business/events/Mandate.resumed) | | [Mandate.revoke](/business/nouns/mandate/revoke?interface=api) | `POST /{namespace}/mandates/{mandate}/revoke` | [`Mandate.revoked`](/business/events/Mandate.revoked) | | [Mandate.spend](/business/nouns/mandate/spend?interface=api) | `POST /{namespace}/mandates/{mandate}/spend` | [`Mandate.spent`](/business/events/Mandate.spent) | ### Mapping | Operation | Route | Event | | --- | --- | --- | | [Mapping.create](/business/nouns/mapping/create?interface=api) | `POST /{namespace}/mappings` | `Mapping.created` | | [Mapping.get](/business/nouns/mapping/get?interface=api) | `GET /{namespace}/mappings/{id}` | None. | | [Mapping.list](/business/nouns/mapping/list?interface=api) | `GET /{namespace}/mappings` | None. | | [Mapping.update](/business/nouns/mapping/update?interface=api) | `PATCH /{namespace}/mappings/{id}` | `Mapping.updated` | | [Mapping.delete](/business/nouns/mapping/delete?interface=api) | `DELETE /{namespace}/mappings/{id}` | `Mapping.deleted` | ### Market | Operation | Route | Event | | --- | --- | --- | | [Market.create](/business/nouns/market/create?interface=api) | `POST /{namespace}/markets` | `Market.created` | | [Market.get](/business/nouns/market/get?interface=api) | `GET /{namespace}/markets/{id}` | None. | | [Market.list](/business/nouns/market/list?interface=api) | `GET /{namespace}/markets` | None. | | [Market.update](/business/nouns/market/update?interface=api) | `PATCH /{namespace}/markets/{id}` | `Market.updated` | | [Market.delete](/business/nouns/market/delete?interface=api) | `DELETE /{namespace}/markets/{id}` | `Market.deleted` | | [Market.enter](/business/nouns/market/enter?interface=api) | `POST /{namespace}/markets/{market}/enter` | [`Market.entered`](/business/events/Market.entered) | ### Meeting | Operation | Route | Event | | --- | --- | --- | | [Meeting.create](/business/nouns/meeting/create?interface=api) | `POST /{namespace}/meetings` | `Meeting.created` | | [Meeting.get](/business/nouns/meeting/get?interface=api) | `GET /{namespace}/meetings/{id}` | None. | | [Meeting.list](/business/nouns/meeting/list?interface=api) | `GET /{namespace}/meetings` | None. | | [Meeting.update](/business/nouns/meeting/update?interface=api) | `PATCH /{namespace}/meetings/{id}` | `Meeting.updated` | | [Meeting.delete](/business/nouns/meeting/delete?interface=api) | `DELETE /{namespace}/meetings/{id}` | `Meeting.deleted` | | [Meeting.book](/business/nouns/meeting/book?interface=api) | `POST /{namespace}/meetings/book` | [`Meeting.booked`](/business/events/Meeting.booked) | ### Member Directory | Operation | Route | Event | | --- | --- | --- | | [MemberDirectory.create](/business/nouns/member-directory/create?interface=api) | `POST /{namespace}/member-directories` | `MemberDirectory.created` | | [MemberDirectory.get](/business/nouns/member-directory/get?interface=api) | `GET /{namespace}/member-directories/{id}` | None. | | [MemberDirectory.list](/business/nouns/member-directory/list?interface=api) | `GET /{namespace}/member-directories` | None. | | [MemberDirectory.update](/business/nouns/member-directory/update?interface=api) | `PATCH /{namespace}/member-directories/{id}` | `MemberDirectory.updated` | | [MemberDirectory.deactivate](/business/nouns/member-directory/deactivate?interface=api) | `POST /{namespace}/member-directories/{directory}/deactivate` | [`MemberDirectory.deactivated`](/business/events/MemberDirectory.deactivated) | | [MemberDirectory.deprovision](/business/nouns/member-directory/deprovision?interface=api) | `POST /{namespace}/member-directories/{directory}/deprovision` | [`MemberDirectory.deprovisioned`](/business/events/MemberDirectory.deprovisioned) | | [MemberDirectory.provision](/business/nouns/member-directory/provision?interface=api) | `POST /{namespace}/member-directories/provision` | [`MemberDirectory.provisioned`](/business/events/MemberDirectory.provisioned) | ### Memory | Operation | Route | Event | | --- | --- | --- | | [Memory.create](/business/nouns/memory/create?interface=api) | `POST /{namespace}/memories` | `Memory.created` | | [Memory.get](/business/nouns/memory/get?interface=api) | `GET /{namespace}/memories/{id}` | None. | | [Memory.list](/business/nouns/memory/list?interface=api) | `GET /{namespace}/memories` | None. | | [Memory.update](/business/nouns/memory/update?interface=api) | `PATCH /{namespace}/memories/{id}` | `Memory.updated` | | [Memory.delete](/business/nouns/memory/delete?interface=api) | `DELETE /{namespace}/memories/{id}` | `Memory.deleted` | ### Message | Operation | Route | Event | | --- | --- | --- | | [Message.create](/business/nouns/message/create?interface=api) | `POST /{namespace}/messages` | `Message.created` | | [Message.get](/business/nouns/message/get?interface=api) | `GET /{namespace}/messages/{id}` | None. | | [Message.list](/business/nouns/message/list?interface=api) | `GET /{namespace}/messages` | None. | | [Message.update](/business/nouns/message/update?interface=api) | `PATCH /{namespace}/messages/{id}` | `Message.updated` | | [Message.delete](/business/nouns/message/delete?interface=api) | `DELETE /{namespace}/messages/{id}` | `Message.deleted` | | [Message.broadcast](/business/nouns/message/broadcast?interface=api) | `POST /{namespace}/messages/{message}/broadcast` | [`Message.broadcasted`](/business/events/Message.broadcasted) | | [Message.schedule](/business/nouns/message/schedule?interface=api) | `POST /{namespace}/messages/{message}/schedule` | [`Message.scheduled`](/business/events/Message.scheduled) | ### Meter | Operation | Route | Event | | --- | --- | --- | | [Meter.create](/business/nouns/meter/create?interface=api) | `POST /{namespace}/meters` | `Meter.created` | | [Meter.get](/business/nouns/meter/get?interface=api) | `GET /{namespace}/meters/{id}` | None. | | [Meter.list](/business/nouns/meter/list?interface=api) | `GET /{namespace}/meters` | None. | | [Meter.update](/business/nouns/meter/update?interface=api) | `PATCH /{namespace}/meters/{id}` | `Meter.updated` | | [Meter.delete](/business/nouns/meter/delete?interface=api) | `DELETE /{namespace}/meters/{id}` | `Meter.deleted` | ### Metric | Operation | Route | Event | | --- | --- | --- | | [Metric.create](/business/nouns/metric/create?interface=api) | `POST /{namespace}/metrics` | `Metric.created` | | [Metric.get](/business/nouns/metric/get?interface=api) | `GET /{namespace}/metrics/{id}` | None. | | [Metric.list](/business/nouns/metric/list?interface=api) | `GET /{namespace}/metrics` | None. | | [Metric.update](/business/nouns/metric/update?interface=api) | `PATCH /{namespace}/metrics/{id}` | `Metric.updated` | | [Metric.delete](/business/nouns/metric/delete?interface=api) | `DELETE /{namespace}/metrics/{id}` | `Metric.deleted` | | [Metric.define](/business/nouns/metric/define?interface=api) | `POST /{namespace}/metrics/define` | [`Metric.defined`](/business/events/Metric.defined) | | [Metric.query](/business/nouns/metric/query?interface=api) | `POST /{namespace}/metrics/query` | [`Metric.queried`](/business/events/Metric.queried) | | [Metric.watch](/business/nouns/metric/watch?interface=api) | `POST /{namespace}/metrics/{metric}/watch` | [`Metric.watched`](/business/events/Metric.watched) | ### Minimum Success Criteria | Operation | Route | Event | | --- | --- | --- | | [MinimumSuccessCriteria.create](/business/nouns/minimum-success-criteria/create?interface=api) | `POST /{namespace}/minimum-success-criteria` | `MinimumSuccessCriteria.created` | | [MinimumSuccessCriteria.get](/business/nouns/minimum-success-criteria/get?interface=api) | `GET /{namespace}/minimum-success-criteria/{id}` | None. | | [MinimumSuccessCriteria.list](/business/nouns/minimum-success-criteria/list?interface=api) | `GET /{namespace}/minimum-success-criteria` | None. | | [MinimumSuccessCriteria.update](/business/nouns/minimum-success-criteria/update?interface=api) | `PATCH /{namespace}/minimum-success-criteria/{id}` | `MinimumSuccessCriteria.updated` | | [MinimumSuccessCriteria.delete](/business/nouns/minimum-success-criteria/delete?interface=api) | `DELETE /{namespace}/minimum-success-criteria/{id}` | `MinimumSuccessCriteria.deleted` | ### Mode | Operation | Route | Event | | --- | --- | --- | | [Mode.get](/business/nouns/mode/get?interface=api) | `GET /{namespace}/modes/{id}` | None. | | [Mode.list](/business/nouns/mode/list?interface=api) | `GET /{namespace}/modes` | None. | ### Monitor | Operation | Route | Event | | --- | --- | --- | | [Monitor.create](/business/nouns/monitor/create?interface=api) | `POST /{namespace}/monitors` | `Monitor.created` | | [Monitor.get](/business/nouns/monitor/get?interface=api) | `GET /{namespace}/monitors/{id}` | None. | | [Monitor.list](/business/nouns/monitor/list?interface=api) | `GET /{namespace}/monitors` | None. | | [Monitor.update](/business/nouns/monitor/update?interface=api) | `PATCH /{namespace}/monitors/{id}` | `Monitor.updated` | | [Monitor.check](/business/nouns/monitor/check?interface=api) | `POST /{namespace}/monitors/{monitor}/check` | [`Monitor.checked`](/business/events/Monitor.checked) | ### Motion | Operation | Route | Event | | --- | --- | --- | | [Motion.get](/business/nouns/motion/get?interface=api) | `GET /{namespace}/motions/{id}` | None. | | [Motion.list](/business/nouns/motion/list?interface=api) | `GET /{namespace}/motions` | None. | ### Noun | Operation | Route | Event | | --- | --- | --- | | [Noun.create](/business/nouns/noun/create?interface=api) | `POST /{namespace}/nouns` | `Noun.created` | | [Noun.get](/business/nouns/noun/get?interface=api) | `GET /{namespace}/nouns/{id}` | None. | | [Noun.list](/business/nouns/noun/list?interface=api) | `GET /{namespace}/nouns` | None. | | [Noun.update](/business/nouns/noun/update?interface=api) | `PATCH /{namespace}/nouns/{id}` | `Noun.updated` | | [Noun.delete](/business/nouns/noun/delete?interface=api) | `DELETE /{namespace}/nouns/{id}` | `Noun.deleted` | | [Noun.retire](/business/nouns/noun/retire?interface=api) | `POST /{namespace}/nouns/{noun}/retire` | [`Noun.retired`](/business/events/Noun.retired) | | [Noun.trace](/business/nouns/noun/trace?interface=api) | `POST /{namespace}/nouns/{noun}/trace` | [`Noun.traced`](/business/events/Noun.traced) | ### Offer | Operation | Route | Event | | --- | --- | --- | | [Offer.create](/business/nouns/offer/create?interface=api) | `POST /{namespace}/offers` | `Offer.created` | | [Offer.get](/business/nouns/offer/get?interface=api) | `GET /{namespace}/offers/{id}` | None. | | [Offer.list](/business/nouns/offer/list?interface=api) | `GET /{namespace}/offers` | None. | | [Offer.update](/business/nouns/offer/update?interface=api) | `PATCH /{namespace}/offers/{id}` | `Offer.updated` | | [Offer.delete](/business/nouns/offer/delete?interface=api) | `DELETE /{namespace}/offers/{id}` | `Offer.deleted` | | [Offer.accept](/business/nouns/offer/accept?interface=api) | `POST /{namespace}/offers/{offer}/accept` | [`Offer.accepted`](/business/events/Offer.accepted) | | [Offer.grant](/business/nouns/offer/grant?interface=api) | `POST /{namespace}/offers/{offer}/grant` | [`Offer.granted`](/business/events/Offer.granted) | | [Offer.publish](/business/nouns/offer/publish?interface=api) | `POST /{namespace}/offers/{offer}/publish` | [`Offer.published`](/business/events/Offer.published) | | [Offer.subscribe](/business/nouns/offer/subscribe?interface=api) | `POST /{namespace}/offers/{offer}/subscribe` | [`Offer.subscribed`](/business/events/Offer.subscribed) | | [Offer.trial](/business/nouns/offer/trial?interface=api) | `POST /{namespace}/offers/{offer}/trial` | [`Offer.trialed`](/business/events/Offer.trialed) | | [Offer.withdraw](/business/nouns/offer/withdraw?interface=api) | `POST /{namespace}/offers/{offer}/withdraw` | [`Offer.withdrawn`](/business/events/Offer.withdrawn) | ### Opening | Operation | Route | Event | | --- | --- | --- | | [Opening.create](/business/nouns/opening/create?interface=api) | `POST /{namespace}/openings` | `Opening.created` | | [Opening.get](/business/nouns/opening/get?interface=api) | `GET /{namespace}/openings/{id}` | None. | | [Opening.list](/business/nouns/opening/list?interface=api) | `GET /{namespace}/openings` | None. | | [Opening.update](/business/nouns/opening/update?interface=api) | `PATCH /{namespace}/openings/{id}` | `Opening.updated` | | [Opening.delete](/business/nouns/opening/delete?interface=api) | `DELETE /{namespace}/openings/{id}` | `Opening.deleted` | ### Order | Operation | Route | Event | | --- | --- | --- | | [Order.create](/business/nouns/order/create?interface=api) | `POST /{namespace}/orders` | `Order.created` | | [Order.get](/business/nouns/order/get?interface=api) | `GET /{namespace}/orders/{id}` | None. | | [Order.list](/business/nouns/order/list?interface=api) | `GET /{namespace}/orders` | None. | | [Order.update](/business/nouns/order/update?interface=api) | `PATCH /{namespace}/orders/{id}` | `Order.updated` | | [Order.cancel](/business/nouns/order/cancel?interface=api) | `POST /{namespace}/orders/{order}/cancel` | [`Order.canceled`](/business/events/Order.canceled) | | [Order.confirm](/business/nouns/order/confirm?interface=api) | `POST /{namespace}/orders/{order}/confirm` | [`Order.confirmed`](/business/events/Order.confirmed) | | [Order.deliver](/business/nouns/order/deliver?interface=api) | `POST /{namespace}/orders/{order}/deliver` | [`Order.delivered`](/business/events/Order.delivered) | | [Order.dispute](/business/nouns/order/dispute?interface=api) | `POST /{namespace}/orders/{order}/dispute` | [`Order.disputed`](/business/events/Order.disputed) | | [Order.fulfill](/business/nouns/order/fulfill?interface=api) | `POST /{namespace}/orders/{order}/fulfill` | [`Order.fulfilled`](/business/events/Order.fulfilled) | | [Order.pay](/business/nouns/order/pay?interface=api) | `POST /{namespace}/orders/{order}/pay` | [`Order.paid`](/business/events/Order.paid) | | [Order.place](/business/nouns/order/place?interface=api) | `POST /{namespace}/orders/place` | [`Order.placed`](/business/events/Order.placed) | | [Order.refund](/business/nouns/order/refund?interface=api) | `POST /{namespace}/orders/{order}/refund` | [`Order.refunded`](/business/events/Order.refunded) | | [Order.revise](/business/nouns/order/revise?interface=api) | `POST /{namespace}/orders/{order}/revise` | [`Order.revised`](/business/events/Order.revised) | | [Order.screen](/business/nouns/order/screen?interface=api) | `POST /{namespace}/orders/{order}/screen` | [`Order.screened`](/business/events/Order.screened) | | [Order.start](/business/nouns/order/start?interface=api) | `POST /{namespace}/orders/{order}/start` | [`Order.started`](/business/events/Order.started) | ### Organization | Operation | Route | Event | | --- | --- | --- | | [Organization.create](/business/nouns/organization/create?interface=api) | `POST /{namespace}/organizations` | `Organization.created` | | [Organization.get](/business/nouns/organization/get?interface=api) | `GET /{namespace}/organizations/{id}` | None. | | [Organization.list](/business/nouns/organization/list?interface=api) | `GET /{namespace}/organizations` | None. | | [Organization.update](/business/nouns/organization/update?interface=api) | `PATCH /{namespace}/organizations/{id}` | `Organization.updated` | | [Organization.delete](/business/nouns/organization/delete?interface=api) | `DELETE /{namespace}/organizations/{id}` | `Organization.deleted` | | [Organization.merge](/business/nouns/organization/merge?interface=api) | `POST /{namespace}/organizations/{organization}/merge` | [`Organization.merged`](/business/events/Organization.merged) | ### Outcome Contract | Operation | Route | Event | | --- | --- | --- | | [OutcomeContract.get](/business/nouns/outcome-contract/get?interface=api) | `GET /{namespace}/outcome-contracts/{id}` | None. | | [OutcomeContract.list](/business/nouns/outcome-contract/list?interface=api) | `GET /{namespace}/outcome-contracts` | None. | | [OutcomeContract.update](/business/nouns/outcome-contract/update?interface=api) | `PATCH /{namespace}/outcome-contracts/{id}` | `OutcomeContract.updated` | ### Page | Operation | Route | Event | | --- | --- | --- | | [Page.create](/business/nouns/page/create?interface=api) | `POST /{namespace}/pages` | `Page.created` | | [Page.get](/business/nouns/page/get?interface=api) | `GET /{namespace}/pages/{id}` | None. | | [Page.list](/business/nouns/page/list?interface=api) | `GET /{namespace}/pages` | None. | | [Page.update](/business/nouns/page/update?interface=api) | `PATCH /{namespace}/pages/{id}` | `Page.updated` | | [Page.delete](/business/nouns/page/delete?interface=api) | `DELETE /{namespace}/pages/{id}` | `Page.deleted` | ### Partner | Operation | Route | Event | | --- | --- | --- | | [Partner.create](/business/nouns/partner/create?interface=api) | `POST /{namespace}/partners` | `Partner.created` | | [Partner.get](/business/nouns/partner/get?interface=api) | `GET /{namespace}/partners/{id}` | None. | | [Partner.list](/business/nouns/partner/list?interface=api) | `GET /{namespace}/partners` | None. | | [Partner.update](/business/nouns/partner/update?interface=api) | `PATCH /{namespace}/partners/{id}` | `Partner.updated` | | [Partner.delete](/business/nouns/partner/delete?interface=api) | `DELETE /{namespace}/partners/{id}` | `Partner.deleted` | ### Party | Operation | Route | Event | | --- | --- | --- | | [Party.create](/business/nouns/party/create?interface=api) | `POST /{namespace}/parties` | `Party.created` | | [Party.get](/business/nouns/party/get?interface=api) | `GET /{namespace}/parties/{id}` | None. | | [Party.list](/business/nouns/party/list?interface=api) | `GET /{namespace}/parties` | None. | | [Party.update](/business/nouns/party/update?interface=api) | `PATCH /{namespace}/parties/{id}` | `Party.updated` | | [Party.delete](/business/nouns/party/delete?interface=api) | `DELETE /{namespace}/parties/{id}` | `Party.deleted` | | [Party.screen](/business/nouns/party/screen?interface=api) | `POST /{namespace}/parties/{party}/screen` | [`Party.screened`](/business/events/Party.screened) | ### Pay Run | Operation | Route | Event | | --- | --- | --- | | [PayRun.get](/business/nouns/pay-run/get?interface=api) | `GET /{namespace}/pay-runs/{id}` | None. | | [PayRun.list](/business/nouns/pay-run/list?interface=api) | `GET /{namespace}/pay-runs` | None. | | [PayRun.approve](/business/nouns/pay-run/approve?interface=api) | `POST /{namespace}/pay-runs/{payRun}/approve` | [`PayRun.approved`](/business/events/PayRun.approved) | | [PayRun.pay](/business/nouns/pay-run/pay?interface=api) | `POST /{namespace}/pay-runs/{payRun}/pay` | [`PayRun.paid`](/business/events/PayRun.paid) | | [PayRun.prepare](/business/nouns/pay-run/prepare?interface=api) | `POST /{namespace}/pay-runs/prepare` | [`PayRun.prepared`](/business/events/PayRun.prepared) | | [PayRun.void](/business/nouns/pay-run/void?interface=api) | `POST /{namespace}/pay-runs/{payRun}/void` | [`PayRun.voided`](/business/events/PayRun.voided) | ### Payment Source | Operation | Route | Event | | --- | --- | --- | | [PaymentSource.get](/business/nouns/payment-source/get?interface=api) | `GET /{namespace}/payment-sources/{id}` | None. | | [PaymentSource.list](/business/nouns/payment-source/list?interface=api) | `GET /{namespace}/payment-sources` | None. | | [PaymentSource.update](/business/nouns/payment-source/update?interface=api) | `PATCH /{namespace}/payment-sources/{id}` | `PaymentSource.updated` | | [PaymentSource.add](/business/nouns/payment-source/add?interface=api) | `POST /{namespace}/payment-sources/add` | [`PaymentSource.added`](/business/events/PaymentSource.added) | | [PaymentSource.remove](/business/nouns/payment-source/remove?interface=api) | `POST /{namespace}/payment-sources/{paymentSource}/remove` | [`PaymentSource.removed`](/business/events/PaymentSource.removed) | ### Period | Operation | Route | Event | | --- | --- | --- | | [Period.get](/business/nouns/period/get?interface=api) | `GET /{namespace}/periods/{id}` | None. | | [Period.list](/business/nouns/period/list?interface=api) | `GET /{namespace}/periods` | None. | | [Period.update](/business/nouns/period/update?interface=api) | `PATCH /{namespace}/periods/{id}` | `Period.updated` | | [Period.close](/business/nouns/period/close?interface=api) | `POST /{namespace}/periods/{period}/close` | [`Period.closed`](/business/events/Period.closed) | | [Period.lock](/business/nouns/period/lock?interface=api) | `POST /{namespace}/periods/{period}/lock` | [`Period.locked`](/business/events/Period.locked) | | [Period.recognize](/business/nouns/period/recognize?interface=api) | `POST /{namespace}/periods/{period}/recognize` | [`Period.recognized`](/business/events/Period.recognized) | ### Permission | Operation | Route | Event | | --- | --- | --- | | [Permission.create](/business/nouns/permission/create?interface=api) | `POST /{namespace}/permissions` | `Permission.created` | | [Permission.get](/business/nouns/permission/get?interface=api) | `GET /{namespace}/permissions/{id}` | None. | | [Permission.list](/business/nouns/permission/list?interface=api) | `GET /{namespace}/permissions` | None. | | [Permission.update](/business/nouns/permission/update?interface=api) | `PATCH /{namespace}/permissions/{id}` | `Permission.updated` | | [Permission.delete](/business/nouns/permission/delete?interface=api) | `DELETE /{namespace}/permissions/{id}` | `Permission.deleted` | ### Person | Operation | Route | Event | | --- | --- | --- | | [Person.create](/business/nouns/person/create?interface=api) | `POST /{namespace}/people` | `Person.created` | | [Person.get](/business/nouns/person/get?interface=api) | `GET /{namespace}/people/{id}` | None. | | [Person.list](/business/nouns/person/list?interface=api) | `GET /{namespace}/people` | None. | | [Person.update](/business/nouns/person/update?interface=api) | `PATCH /{namespace}/people/{id}` | `Person.updated` | | [Person.delete](/business/nouns/person/delete?interface=api) | `DELETE /{namespace}/people/{id}` | `Person.deleted` | ### Persona | Operation | Route | Event | | --- | --- | --- | | [Persona.create](/business/nouns/persona/create?interface=api) | `POST /{namespace}/personas` | `Persona.created` | | [Persona.get](/business/nouns/persona/get?interface=api) | `GET /{namespace}/personas/{id}` | None. | | [Persona.list](/business/nouns/persona/list?interface=api) | `GET /{namespace}/personas` | None. | | [Persona.update](/business/nouns/persona/update?interface=api) | `PATCH /{namespace}/personas/{id}` | `Persona.updated` | | [Persona.delete](/business/nouns/persona/delete?interface=api) | `DELETE /{namespace}/personas/{id}` | `Persona.deleted` | ### Play | Operation | Route | Event | | --- | --- | --- | | [Play.create](/business/nouns/play/create?interface=api) | `POST /{namespace}/plays` | `Play.created` | | [Play.get](/business/nouns/play/get?interface=api) | `GET /{namespace}/plays/{id}` | None. | | [Play.list](/business/nouns/play/list?interface=api) | `GET /{namespace}/plays` | None. | | [Play.update](/business/nouns/play/update?interface=api) | `PATCH /{namespace}/plays/{id}` | `Play.updated` | | [Play.delete](/business/nouns/play/delete?interface=api) | `DELETE /{namespace}/plays/{id}` | `Play.deleted` | | [Play.apply](/business/nouns/play/apply?interface=api) | `POST /{namespace}/plays/{play}/apply` | [`Play.applied`](/business/events/Play.applied) | ### Play Mix | Operation | Route | Event | | --- | --- | --- | | [PlayMix.get](/business/nouns/play-mix/get?interface=api) | `GET /{namespace}/play-mixes/{id}` | None. | | [PlayMix.list](/business/nouns/play-mix/list?interface=api) | `GET /{namespace}/play-mixes` | None. | | [PlayMix.compile](/business/nouns/play-mix/compile?interface=api) | `POST /{namespace}/play-mixes/compile` | [`PlayMix.compiled`](/business/events/PlayMix.compiled) | ### Policy | Operation | Route | Event | | --- | --- | --- | | [Policy.create](/business/nouns/policy/create?interface=api) | `POST /{namespace}/policies` | `Policy.created` | | [Policy.get](/business/nouns/policy/get?interface=api) | `GET /{namespace}/policies/{id}` | None. | | [Policy.list](/business/nouns/policy/list?interface=api) | `GET /{namespace}/policies` | None. | | [Policy.update](/business/nouns/policy/update?interface=api) | `PATCH /{namespace}/policies/{id}` | `Policy.updated` | | [Policy.delete](/business/nouns/policy/delete?interface=api) | `DELETE /{namespace}/policies/{id}` | `Policy.deleted` | ### Portal | Operation | Route | Event | | --- | --- | --- | | [Portal.create](/business/nouns/portal/create?interface=api) | `POST /{namespace}/portals` | `Portal.created` | | [Portal.get](/business/nouns/portal/get?interface=api) | `GET /{namespace}/portals/{id}` | None. | | [Portal.list](/business/nouns/portal/list?interface=api) | `GET /{namespace}/portals` | None. | | [Portal.update](/business/nouns/portal/update?interface=api) | `PATCH /{namespace}/portals/{id}` | `Portal.updated` | | [Portal.delete](/business/nouns/portal/delete?interface=api) | `DELETE /{namespace}/portals/{id}` | `Portal.deleted` | ### Portfolio | Operation | Route | Event | | --- | --- | --- | | [Portfolio.create](/business/nouns/portfolio/create?interface=api) | `POST /{namespace}/portfolios` | `Portfolio.created` | | [Portfolio.get](/business/nouns/portfolio/get?interface=api) | `GET /{namespace}/portfolios/{id}` | None. | | [Portfolio.list](/business/nouns/portfolio/list?interface=api) | `GET /{namespace}/portfolios` | None. | | [Portfolio.update](/business/nouns/portfolio/update?interface=api) | `PATCH /{namespace}/portfolios/{id}` | `Portfolio.updated` | | [Portfolio.delete](/business/nouns/portfolio/delete?interface=api) | `DELETE /{namespace}/portfolios/{id}` | `Portfolio.deleted` | | [Portfolio.brake](/business/nouns/portfolio/brake?interface=api) | `POST /{namespace}/portfolios/{portfolio}/brake` | [`Portfolio.braked`](/business/events/Portfolio.braked) | | [Portfolio.lift](/business/nouns/portfolio/lift?interface=api) | `POST /{namespace}/portfolios/{portfolio}/lift` | [`Portfolio.lifted`](/business/events/Portfolio.lifted) | ### Post | Operation | Route | Event | | --- | --- | --- | | [Post.create](/business/nouns/post/create?interface=api) | `POST /{namespace}/posts` | `Post.created` | | [Post.get](/business/nouns/post/get?interface=api) | `GET /{namespace}/posts/{id}` | None. | | [Post.list](/business/nouns/post/list?interface=api) | `GET /{namespace}/posts` | None. | | [Post.update](/business/nouns/post/update?interface=api) | `PATCH /{namespace}/posts/{id}` | `Post.updated` | | [Post.publish](/business/nouns/post/publish?interface=api) | `POST /{namespace}/posts/{post}/publish` | [`Post.published`](/business/events/Post.published) | | [Post.schedule](/business/nouns/post/schedule?interface=api) | `POST /{namespace}/posts/{post}/schedule` | [`Post.scheduled`](/business/events/Post.scheduled) | | [Post.withdraw](/business/nouns/post/withdraw?interface=api) | `POST /{namespace}/posts/{post}/withdraw` | [`Post.withdrawn`](/business/events/Post.withdrawn) | ### Problem | Operation | Route | Event | | --- | --- | --- | | [Problem.create](/business/nouns/problem/create?interface=api) | `POST /{namespace}/problems` | `Problem.created` | | [Problem.get](/business/nouns/problem/get?interface=api) | `GET /{namespace}/problems/{id}` | None. | | [Problem.list](/business/nouns/problem/list?interface=api) | `GET /{namespace}/problems` | None. | | [Problem.update](/business/nouns/problem/update?interface=api) | `PATCH /{namespace}/problems/{id}` | `Problem.updated` | | [Problem.delete](/business/nouns/problem/delete?interface=api) | `DELETE /{namespace}/problems/{id}` | `Problem.deleted` | | [Problem.rank](/business/nouns/problem/rank?interface=api) | `POST /{namespace}/problems/rank` | [`Problem.ranked`](/business/events/Problem.ranked) | | [Problem.suggest](/business/nouns/problem/suggest?interface=api) | `POST /{namespace}/problems/suggest` | [`Problem.suggested`](/business/events/Problem.suggested) | ### Process | Operation | Route | Event | | --- | --- | --- | | [Process.create](/business/nouns/process/create?interface=api) | `POST /{namespace}/processes` | `Process.created` | | [Process.get](/business/nouns/process/get?interface=api) | `GET /{namespace}/processes/{id}` | None. | | [Process.list](/business/nouns/process/list?interface=api) | `GET /{namespace}/processes` | None. | | [Process.update](/business/nouns/process/update?interface=api) | `PATCH /{namespace}/processes/{id}` | `Process.updated` | | [Process.delete](/business/nouns/process/delete?interface=api) | `DELETE /{namespace}/processes/{id}` | `Process.deleted` | | [Process.enable](/business/nouns/process/enable?interface=api) | `POST /{namespace}/processes/{process}/enable` | [`Process.enabled`](/business/events/Process.enabled) | | [Process.pause](/business/nouns/process/pause?interface=api) | `POST /{namespace}/processes/{process}/pause` | [`Process.paused`](/business/events/Process.paused) | ### Product | Operation | Route | Event | | --- | --- | --- | | [Product.create](/business/nouns/product/create?interface=api) | `POST /{namespace}/products` | `Product.created` | | [Product.get](/business/nouns/product/get?interface=api) | `GET /{namespace}/products/{id}` | None. | | [Product.list](/business/nouns/product/list?interface=api) | `GET /{namespace}/products` | None. | | [Product.update](/business/nouns/product/update?interface=api) | `PATCH /{namespace}/products/{id}` | `Product.updated` | | [Product.delete](/business/nouns/product/delete?interface=api) | `DELETE /{namespace}/products/{id}` | `Product.deleted` | ### Product Template | Operation | Route | Event | | --- | --- | --- | | [ProductTemplate.create](/business/nouns/product-template/create?interface=api) | `POST /{namespace}/product-templates` | `ProductTemplate.created` | | [ProductTemplate.get](/business/nouns/product-template/get?interface=api) | `GET /{namespace}/product-templates/{id}` | None. | | [ProductTemplate.list](/business/nouns/product-template/list?interface=api) | `GET /{namespace}/product-templates` | None. | | [ProductTemplate.update](/business/nouns/product-template/update?interface=api) | `PATCH /{namespace}/product-templates/{id}` | `ProductTemplate.updated` | | [ProductTemplate.delete](/business/nouns/product-template/delete?interface=api) | `DELETE /{namespace}/product-templates/{id}` | `ProductTemplate.deleted` | ### Project | Operation | Route | Event | | --- | --- | --- | | [Project.create](/business/nouns/project/create?interface=api) | `POST /{namespace}/projects` | `Project.created` | | [Project.get](/business/nouns/project/get?interface=api) | `GET /{namespace}/projects/{id}` | None. | | [Project.list](/business/nouns/project/list?interface=api) | `GET /{namespace}/projects` | None. | | [Project.update](/business/nouns/project/update?interface=api) | `PATCH /{namespace}/projects/{id}` | `Project.updated` | | [Project.delete](/business/nouns/project/delete?interface=api) | `DELETE /{namespace}/projects/{id}` | `Project.deleted` | ### Proof | Operation | Route | Event | | --- | --- | --- | | [Proof.get](/business/nouns/proof/get?interface=api) | `GET /{namespace}/proofs/{id}` | None. | | [Proof.list](/business/nouns/proof/list?interface=api) | `GET /{namespace}/proofs` | None. | ### Prospect | Operation | Route | Event | | --- | --- | --- | | [Prospect.create](/business/nouns/prospect/create?interface=api) | `POST /{namespace}/prospects` | `Prospect.created` | | [Prospect.get](/business/nouns/prospect/get?interface=api) | `GET /{namespace}/prospects/{id}` | None. | | [Prospect.list](/business/nouns/prospect/list?interface=api) | `GET /{namespace}/prospects` | None. | | [Prospect.update](/business/nouns/prospect/update?interface=api) | `PATCH /{namespace}/prospects/{id}` | `Prospect.updated` | | [Prospect.delete](/business/nouns/prospect/delete?interface=api) | `DELETE /{namespace}/prospects/{id}` | `Prospect.deleted` | | [Prospect.engage](/business/nouns/prospect/engage?interface=api) | `POST /{namespace}/prospects/{prospect}/engage` | [`Prospect.engaged`](/business/events/Prospect.engaged) | ### Publication | Operation | Route | Event | | --- | --- | --- | | [Publication.get](/business/nouns/publication/get?interface=api) | `GET /{namespace}/publications/{id}` | None. | | [Publication.list](/business/nouns/publication/list?interface=api) | `GET /{namespace}/publications` | None. | ### Purpose | Operation | Route | Event | | --- | --- | --- | | [Purpose.create](/business/nouns/purpose/create?interface=api) | `POST /{namespace}/purposes` | `Purpose.created` | | [Purpose.get](/business/nouns/purpose/get?interface=api) | `GET /{namespace}/purposes/{id}` | None. | | [Purpose.list](/business/nouns/purpose/list?interface=api) | `GET /{namespace}/purposes` | None. | | [Purpose.update](/business/nouns/purpose/update?interface=api) | `PATCH /{namespace}/purposes/{id}` | `Purpose.updated` | | [Purpose.delete](/business/nouns/purpose/delete?interface=api) | `DELETE /{namespace}/purposes/{id}` | `Purpose.deleted` | ### Question | Operation | Route | Event | | --- | --- | --- | | [Question.get](/business/nouns/question/get?interface=api) | `GET /{namespace}/questions/{id}` | None. | | [Question.list](/business/nouns/question/list?interface=api) | `GET /{namespace}/questions` | None. | ### Quote | Operation | Route | Event | | --- | --- | --- | | [Quote.create](/business/nouns/quote/create?interface=api) | `POST /{namespace}/quotes` | `Quote.created` | | [Quote.get](/business/nouns/quote/get?interface=api) | `GET /{namespace}/quotes/{id}` | None. | | [Quote.list](/business/nouns/quote/list?interface=api) | `GET /{namespace}/quotes` | None. | | [Quote.update](/business/nouns/quote/update?interface=api) | `PATCH /{namespace}/quotes/{id}` | `Quote.updated` | | [Quote.delete](/business/nouns/quote/delete?interface=api) | `DELETE /{namespace}/quotes/{id}` | `Quote.deleted` | | [Quote.accept](/business/nouns/quote/accept?interface=api) | `POST /{namespace}/quotes/{quote}/accept` | [`Quote.accepted`](/business/events/Quote.accepted) | | [Quote.decline](/business/nouns/quote/decline?interface=api) | `POST /{namespace}/quotes/{quote}/decline` | [`Quote.declined`](/business/events/Quote.declined) | | [Quote.expire](/business/nouns/quote/expire?interface=api) | `POST /{namespace}/quotes/{quote}/expire` | [`Quote.expired`](/business/events/Quote.expired) | | [Quote.request](/business/nouns/quote/request?interface=api) | `POST /{namespace}/quotes/request` | [`Quote.requested`](/business/events/Quote.requested) | | [Quote.send](/business/nouns/quote/send?interface=api) | `POST /{namespace}/quotes/{quote}/send` | [`Quote.sent`](/business/events/Quote.sent) | | [Quote.supersede](/business/nouns/quote/supersede?interface=api) | `POST /{namespace}/quotes/{quote}/supersede` | [`Quote.superseded`](/business/events/Quote.superseded) | ### Readout | Operation | Route | Event | | --- | --- | --- | | [Readout.create](/business/nouns/readout/create?interface=api) | `POST /{namespace}/readouts` | `Readout.created` | | [Readout.get](/business/nouns/readout/get?interface=api) | `GET /{namespace}/readouts/{id}` | None. | | [Readout.list](/business/nouns/readout/list?interface=api) | `GET /{namespace}/readouts` | None. | | [Readout.update](/business/nouns/readout/update?interface=api) | `PATCH /{namespace}/readouts/{id}` | `Readout.updated` | | [Readout.delete](/business/nouns/readout/delete?interface=api) | `DELETE /{namespace}/readouts/{id}` | `Readout.deleted` | ### Recording | Operation | Route | Event | | --- | --- | --- | | [Recording.get](/business/nouns/recording/get?interface=api) | `GET /{namespace}/recordings/{id}` | None. | | [Recording.list](/business/nouns/recording/list?interface=api) | `GET /{namespace}/recordings` | None. | ### Recovery Objective | Operation | Route | Event | | --- | --- | --- | | [RecoveryObjective.create](/business/nouns/recovery-objective/create?interface=api) | `POST /{namespace}/recovery-objectives` | `RecoveryObjective.created` | | [RecoveryObjective.get](/business/nouns/recovery-objective/get?interface=api) | `GET /{namespace}/recovery-objectives/{id}` | None. | | [RecoveryObjective.list](/business/nouns/recovery-objective/list?interface=api) | `GET /{namespace}/recovery-objectives` | None. | | [RecoveryObjective.update](/business/nouns/recovery-objective/update?interface=api) | `PATCH /{namespace}/recovery-objectives/{id}` | `RecoveryObjective.updated` | | [RecoveryObjective.delete](/business/nouns/recovery-objective/delete?interface=api) | `DELETE /{namespace}/recovery-objectives/{id}` | `RecoveryObjective.deleted` | | [RecoveryObjective.drill](/business/nouns/recovery-objective/drill?interface=api) | `POST /{namespace}/recovery-objectives/{objective}/drill` | [`RecoveryObjective.drilled`](/business/events/RecoveryObjective.drilled) | ### Referral | Operation | Route | Event | | --- | --- | --- | | [Referral.create](/business/nouns/referral/create?interface=api) | `POST /{namespace}/referrals` | `Referral.created` | | [Referral.get](/business/nouns/referral/get?interface=api) | `GET /{namespace}/referrals/{id}` | None. | | [Referral.list](/business/nouns/referral/list?interface=api) | `GET /{namespace}/referrals` | None. | | [Referral.update](/business/nouns/referral/update?interface=api) | `PATCH /{namespace}/referrals/{id}` | `Referral.updated` | | [Referral.delete](/business/nouns/referral/delete?interface=api) | `DELETE /{namespace}/referrals/{id}` | `Referral.deleted` | ### Registration | Operation | Route | Event | | --- | --- | --- | | [Registration.create](/business/nouns/registration/create?interface=api) | `POST /{namespace}/registrations` | `Registration.created` | | [Registration.get](/business/nouns/registration/get?interface=api) | `GET /{namespace}/registrations/{id}` | None. | | [Registration.list](/business/nouns/registration/list?interface=api) | `GET /{namespace}/registrations` | None. | | [Registration.update](/business/nouns/registration/update?interface=api) | `PATCH /{namespace}/registrations/{id}` | `Registration.updated` | | [Registration.delete](/business/nouns/registration/delete?interface=api) | `DELETE /{namespace}/registrations/{id}` | `Registration.deleted` | | [Registration.admit](/business/nouns/registration/admit?interface=api) | `POST /{namespace}/registrations/{registration}/admit` | [`Registration.admitted`](/business/events/Registration.admitted) | | [Registration.approve](/business/nouns/registration/approve?interface=api) | `POST /{namespace}/registrations/{registration}/approve` | [`Registration.approved`](/business/events/Registration.approved) | | [Registration.attend](/business/nouns/registration/attend?interface=api) | `POST /{namespace}/registrations/{registration}/attend` | [`Registration.attended`](/business/events/Registration.attended) | ### Relationship | Operation | Route | Event | | --- | --- | --- | | [Relationship.create](/business/nouns/relationship/create?interface=api) | `POST /{namespace}/relationships` | `Relationship.created` | | [Relationship.get](/business/nouns/relationship/get?interface=api) | `GET /{namespace}/relationships/{id}` | None. | | [Relationship.list](/business/nouns/relationship/list?interface=api) | `GET /{namespace}/relationships` | None. | | [Relationship.update](/business/nouns/relationship/update?interface=api) | `PATCH /{namespace}/relationships/{id}` | `Relationship.updated` | | [Relationship.delete](/business/nouns/relationship/delete?interface=api) | `DELETE /{namespace}/relationships/{id}` | `Relationship.deleted` | ### Renewal | Operation | Route | Event | | --- | --- | --- | | [Renewal.create](/business/nouns/renewal/create?interface=api) | `POST /{namespace}/renewals` | `Renewal.created` | | [Renewal.get](/business/nouns/renewal/get?interface=api) | `GET /{namespace}/renewals/{id}` | None. | | [Renewal.list](/business/nouns/renewal/list?interface=api) | `GET /{namespace}/renewals` | None. | | [Renewal.update](/business/nouns/renewal/update?interface=api) | `PATCH /{namespace}/renewals/{id}` | `Renewal.updated` | | [Renewal.delete](/business/nouns/renewal/delete?interface=api) | `DELETE /{namespace}/renewals/{id}` | `Renewal.deleted` | | [Renewal.open](/business/nouns/renewal/open?interface=api) | `POST /{namespace}/renewals/open` | [`Renewal.opened`](/business/events/Renewal.opened) | ### Reserved Act | Operation | Route | Event | | --- | --- | --- | | [ReservedAct.create](/business/nouns/reserved-act/create?interface=api) | `POST /{namespace}/reserved-acts` | `ReservedAct.created` | | [ReservedAct.get](/business/nouns/reserved-act/get?interface=api) | `GET /{namespace}/reserved-acts/{id}` | None. | | [ReservedAct.list](/business/nouns/reserved-act/list?interface=api) | `GET /{namespace}/reserved-acts` | None. | | [ReservedAct.update](/business/nouns/reserved-act/update?interface=api) | `PATCH /{namespace}/reserved-acts/{id}` | `ReservedAct.updated` | | [ReservedAct.delete](/business/nouns/reserved-act/delete?interface=api) | `DELETE /{namespace}/reserved-acts/{id}` | `ReservedAct.deleted` | ### Review | Operation | Route | Event | | --- | --- | --- | | [Review.create](/business/nouns/review/create?interface=api) | `POST /{namespace}/reviews` | `Review.created` | | [Review.get](/business/nouns/review/get?interface=api) | `GET /{namespace}/reviews/{id}` | None. | | [Review.list](/business/nouns/review/list?interface=api) | `GET /{namespace}/reviews` | None. | | [Review.update](/business/nouns/review/update?interface=api) | `PATCH /{namespace}/reviews/{id}` | `Review.updated` | | [Review.publish](/business/nouns/review/publish?interface=api) | `POST /{namespace}/reviews/{review}/publish` | [`Review.published`](/business/events/Review.published) | | [Review.remove](/business/nouns/review/remove?interface=api) | `POST /{namespace}/reviews/{review}/remove` | [`Review.removed`](/business/events/Review.removed) | | [Review.withhold](/business/nouns/review/withhold?interface=api) | `POST /{namespace}/reviews/{review}/withhold` | [`Review.withheld`](/business/events/Review.withheld) | ### Risk | Operation | Route | Event | | --- | --- | --- | | [Risk.create](/business/nouns/risk/create?interface=api) | `POST /{namespace}/risks` | `Risk.created` | | [Risk.get](/business/nouns/risk/get?interface=api) | `GET /{namespace}/risks/{id}` | None. | | [Risk.list](/business/nouns/risk/list?interface=api) | `GET /{namespace}/risks` | None. | | [Risk.update](/business/nouns/risk/update?interface=api) | `PATCH /{namespace}/risks/{id}` | `Risk.updated` | | [Risk.accept](/business/nouns/risk/accept?interface=api) | `POST /{namespace}/risks/{risk}/accept` | [`Risk.accepted`](/business/events/Risk.accepted) | | [Risk.assess](/business/nouns/risk/assess?interface=api) | `POST /{namespace}/risks/{risk}/assess` | [`Risk.assessed`](/business/events/Risk.assessed) | | [Risk.close](/business/nouns/risk/close?interface=api) | `POST /{namespace}/risks/{risk}/close` | [`Risk.closed`](/business/events/Risk.closed) | | [Risk.treat](/business/nouns/risk/treat?interface=api) | `POST /{namespace}/risks/{risk}/treat` | [`Risk.treated`](/business/events/Risk.treated) | ### Role | Operation | Route | Event | | --- | --- | --- | | [Role.create](/business/nouns/role/create?interface=api) | `POST /{namespace}/roles` | `Role.created` | | [Role.get](/business/nouns/role/get?interface=api) | `GET /{namespace}/roles/{id}` | None. | | [Role.list](/business/nouns/role/list?interface=api) | `GET /{namespace}/roles` | None. | | [Role.update](/business/nouns/role/update?interface=api) | `PATCH /{namespace}/roles/{id}` | `Role.updated` | | [Role.delete](/business/nouns/role/delete?interface=api) | `DELETE /{namespace}/roles/{id}` | `Role.deleted` | | [Role.review](/business/nouns/role/review?interface=api) | `POST /{namespace}/roles/{role}/review` | [`Role.reviewed`](/business/events/Role.reviewed) | | [Role.staff](/business/nouns/role/staff?interface=api) | `POST /{namespace}/roles/{role}/staff` | [`Role.staffed`](/business/events/Role.staffed) | | [Role.vacate](/business/nouns/role/vacate?interface=api) | `POST /{namespace}/roles/{role}/vacate` | [`Role.vacated`](/business/events/Role.vacated) | ### Role Review | Operation | Route | Event | | --- | --- | --- | | [RoleReview.get](/business/nouns/role-review/get?interface=api) | `GET /{namespace}/role-reviews/{id}` | None. | | [RoleReview.list](/business/nouns/role-review/list?interface=api) | `GET /{namespace}/role-reviews` | None. | ### Screening | Operation | Route | Event | | --- | --- | --- | | [Screening.get](/business/nouns/screening/get?interface=api) | `GET /{namespace}/screenings/{id}` | None. | | [Screening.list](/business/nouns/screening/list?interface=api) | `GET /{namespace}/screenings` | None. | ### Secret | Operation | Route | Event | | --- | --- | --- | | [Secret.get](/business/nouns/secret/get?interface=api) | `GET /{namespace}/secrets/{id}` | None. | | [Secret.list](/business/nouns/secret/list?interface=api) | `GET /{namespace}/secrets` | None. | | [Secret.revoke](/business/nouns/secret/revoke?interface=api) | `POST /{namespace}/secrets/{secret}/revoke` | [`Secret.revoked`](/business/events/Secret.revoked) | | [Secret.rotate](/business/nouns/secret/rotate?interface=api) | `POST /{namespace}/secrets/{secret}/rotate` | [`Secret.rotated`](/business/events/Secret.rotated) | | [Secret.store](/business/nouns/secret/store?interface=api) | `POST /{namespace}/secrets/store` | [`Secret.stored`](/business/events/Secret.stored) | ### Sequence | Operation | Route | Event | | --- | --- | --- | | [Sequence.create](/business/nouns/sequence/create?interface=api) | `POST /{namespace}/sequences` | `Sequence.created` | | [Sequence.get](/business/nouns/sequence/get?interface=api) | `GET /{namespace}/sequences/{id}` | None. | | [Sequence.list](/business/nouns/sequence/list?interface=api) | `GET /{namespace}/sequences` | None. | | [Sequence.update](/business/nouns/sequence/update?interface=api) | `PATCH /{namespace}/sequences/{id}` | `Sequence.updated` | | [Sequence.delete](/business/nouns/sequence/delete?interface=api) | `DELETE /{namespace}/sequences/{id}` | `Sequence.deleted` | ### Service | Operation | Route | Event | | --- | --- | --- | | [Service.create](/business/nouns/service/create?interface=api) | `POST /{namespace}/services` | `Service.created` | | [Service.get](/business/nouns/service/get?interface=api) | `GET /{namespace}/services/{id}` | None. | | [Service.list](/business/nouns/service/list?interface=api) | `GET /{namespace}/services` | None. | | [Service.update](/business/nouns/service/update?interface=api) | `PATCH /{namespace}/services/{id}` | `Service.updated` | | [Service.delete](/business/nouns/service/delete?interface=api) | `DELETE /{namespace}/services/{id}` | `Service.deleted` | ### Setting | Operation | Route | Event | | --- | --- | --- | | [Setting.create](/business/nouns/setting/create?interface=api) | `POST /{namespace}/settings` | `Setting.created` | | [Setting.get](/business/nouns/setting/get?interface=api) | `GET /{namespace}/settings/{id}` | None. | | [Setting.list](/business/nouns/setting/list?interface=api) | `GET /{namespace}/settings` | None. | | [Setting.update](/business/nouns/setting/update?interface=api) | `PATCH /{namespace}/settings/{id}` | `Setting.updated` | | [Setting.delete](/business/nouns/setting/delete?interface=api) | `DELETE /{namespace}/settings/{id}` | `Setting.deleted` | ### Share | Operation | Route | Event | | --- | --- | --- | | [Share.get](/business/nouns/share/get?interface=api) | `GET /{namespace}/shares/{id}` | None. | | [Share.list](/business/nouns/share/list?interface=api) | `GET /{namespace}/shares` | None. | | [Share.issue](/business/nouns/share/issue?interface=api) | `POST /{namespace}/shares/issue` | [`Share.issued`](/business/events/Share.issued) | | [Share.transfer](/business/nouns/share/transfer?interface=api) | `POST /{namespace}/shares/{share}/transfer` | [`Share.transferred`](/business/events/Share.transferred) | ### Site | Operation | Route | Event | | --- | --- | --- | | [Site.create](/business/nouns/site/create?interface=api) | `POST /{namespace}/sites` | `Site.created` | | [Site.get](/business/nouns/site/get?interface=api) | `GET /{namespace}/sites/{id}` | None. | | [Site.list](/business/nouns/site/list?interface=api) | `GET /{namespace}/sites` | None. | | [Site.update](/business/nouns/site/update?interface=api) | `PATCH /{namespace}/sites/{id}` | `Site.updated` | | [Site.delete](/business/nouns/site/delete?interface=api) | `DELETE /{namespace}/sites/{id}` | `Site.deleted` | | [Site.publish](/business/nouns/site/publish?interface=api) | `POST /{namespace}/sites/{site}/publish` | [`Site.published`](/business/events/Site.published) | ### Skill | Operation | Route | Event | | --- | --- | --- | | [Skill.create](/business/nouns/skill/create?interface=api) | `POST /{namespace}/skills` | `Skill.created` | | [Skill.get](/business/nouns/skill/get?interface=api) | `GET /{namespace}/skills/{id}` | None. | | [Skill.list](/business/nouns/skill/list?interface=api) | `GET /{namespace}/skills` | None. | | [Skill.update](/business/nouns/skill/update?interface=api) | `PATCH /{namespace}/skills/{id}` | `Skill.updated` | | [Skill.delete](/business/nouns/skill/delete?interface=api) | `DELETE /{namespace}/skills/{id}` | `Skill.deleted` | ### Software | Operation | Route | Event | | --- | --- | --- | | [Software.create](/business/nouns/software/create?interface=api) | `POST /{namespace}/software` | `Software.created` | | [Software.get](/business/nouns/software/get?interface=api) | `GET /{namespace}/software/{id}` | None. | | [Software.list](/business/nouns/software/list?interface=api) | `GET /{namespace}/software` | None. | | [Software.update](/business/nouns/software/update?interface=api) | `PATCH /{namespace}/software/{id}` | `Software.updated` | | [Software.delete](/business/nouns/software/delete?interface=api) | `DELETE /{namespace}/software/{id}` | `Software.deleted` | ### Source | Operation | Route | Event | | --- | --- | --- | | [Source.create](/business/nouns/source/create?interface=api) | `POST /{namespace}/sources` | `Source.created` | | [Source.get](/business/nouns/source/get?interface=api) | `GET /{namespace}/sources/{id}` | None. | | [Source.list](/business/nouns/source/list?interface=api) | `GET /{namespace}/sources` | None. | | [Source.update](/business/nouns/source/update?interface=api) | `PATCH /{namespace}/sources/{id}` | `Source.updated` | | [Source.delete](/business/nouns/source/delete?interface=api) | `DELETE /{namespace}/sources/{id}` | `Source.deleted` | ### SSO Connection | Operation | Route | Event | | --- | --- | --- | | [SSOConnection.create](/business/nouns/sso-connection/create?interface=api) | `POST /{namespace}/sso-connections` | `SSOConnection.created` | | [SSOConnection.get](/business/nouns/sso-connection/get?interface=api) | `GET /{namespace}/sso-connections/{id}` | None. | | [SSOConnection.list](/business/nouns/sso-connection/list?interface=api) | `GET /{namespace}/sso-connections` | None. | | [SSOConnection.update](/business/nouns/sso-connection/update?interface=api) | `PATCH /{namespace}/sso-connections/{id}` | `SSOConnection.updated` | | [SSOConnection.activate](/business/nouns/sso-connection/activate?interface=api) | `POST /{namespace}/sso-connections/{connection}/activate` | [`SSOConnection.activated`](/business/events/SSOConnection.activated) | | [SSOConnection.deactivate](/business/nouns/sso-connection/deactivate?interface=api) | `POST /{namespace}/sso-connections/{connection}/deactivate` | [`SSOConnection.deactivated`](/business/events/SSOConnection.deactivated) | ### Standard | Operation | Route | Event | | --- | --- | --- | | [Standard.get](/business/nouns/standard/get?interface=api) | `GET /{namespace}/standards/{id}` | None. | | [Standard.list](/business/nouns/standard/list?interface=api) | `GET /{namespace}/standards` | None. | ### Startup | Operation | Route | Event | | --- | --- | --- | | [Startup.create](/business/nouns/startup/create?interface=api) | `POST /{namespace}/startups` | `Startup.created` | | [Startup.get](/business/nouns/startup/get?interface=api) | `GET /{namespace}/startups/{id}` | None. | | [Startup.list](/business/nouns/startup/list?interface=api) | `GET /{namespace}/startups` | None. | | [Startup.update](/business/nouns/startup/update?interface=api) | `PATCH /{namespace}/startups/{id}` | `Startup.updated` | | [Startup.delete](/business/nouns/startup/delete?interface=api) | `DELETE /{namespace}/startups/{id}` | `Startup.deleted` | | [Startup.advance](/business/nouns/startup/advance?interface=api) | `POST /{namespace}/startups/{startup}/advance` | [`Startup.advanced`](/business/events/Startup.advanced) | | [Startup.build](/business/nouns/startup/build?interface=api) | `POST /{namespace}/startups/{startup}/build` | [`Startup.built`](/business/events/Startup.built) | | [Startup.claim](/business/nouns/startup/claim?interface=api) | `POST /{namespace}/startups/{startup}/claim` | [`Startup.claimed`](/business/events/Startup.claimed) | | [Startup.clone](/business/nouns/startup/clone?interface=api) | `POST /{namespace}/startups/{startup}/clone` | [`Startup.cloned`](/business/events/Startup.cloned) | | [Startup.graduate](/business/nouns/startup/graduate?interface=api) | `POST /{namespace}/startups/{startup}/graduate` | [`Startup.graduated`](/business/events/Startup.graduated) | | [Startup.hold](/business/nouns/startup/hold?interface=api) | `POST /{namespace}/startups/{startup}/hold` | [`Startup.held`](/business/events/Startup.held) | | [Startup.import](/business/nouns/startup/import?interface=api) | `POST /{namespace}/startups/import` | [`Startup.imported`](/business/events/Startup.imported) | | [Startup.launch](/business/nouns/startup/launch?interface=api) | `POST /{namespace}/startups/{startup}/launch` | [`Startup.launched`](/business/events/Startup.launched) | | [Startup.pause](/business/nouns/startup/pause?interface=api) | `POST /{namespace}/startups/{startup}/pause` | [`Startup.paused`](/business/events/Startup.paused) | | [Startup.pivot](/business/nouns/startup/pivot?interface=api) | `POST /{namespace}/startups/{startup}/pivot` | [`Startup.pivoted`](/business/events/Startup.pivoted) | | [Startup.read](/business/nouns/startup/read?interface=api) | `POST /{namespace}/startups/{startup}/read` | [`Startup.read`](/business/events/Startup.read) | | [Startup.resume](/business/nouns/startup/resume?interface=api) | `POST /{namespace}/startups/{startup}/resume` | [`Startup.resumed`](/business/events/Startup.resumed) | | [Startup.sell](/business/nouns/startup/sell?interface=api) | `POST /{namespace}/startups/{startup}/sell` | [`Startup.sold`](/business/events/Startup.sold) | ### Startup Template | Operation | Route | Event | | --- | --- | --- | | [StartupTemplate.create](/business/nouns/startup-template/create?interface=api) | `POST /{namespace}/startup-templates` | `StartupTemplate.created` | | [StartupTemplate.get](/business/nouns/startup-template/get?interface=api) | `GET /{namespace}/startup-templates/{id}` | None. | | [StartupTemplate.list](/business/nouns/startup-template/list?interface=api) | `GET /{namespace}/startup-templates` | None. | | [StartupTemplate.update](/business/nouns/startup-template/update?interface=api) | `PATCH /{namespace}/startup-templates/{id}` | `StartupTemplate.updated` | | [StartupTemplate.delete](/business/nouns/startup-template/delete?interface=api) | `DELETE /{namespace}/startup-templates/{id}` | `StartupTemplate.deleted` | | [StartupTemplate.extend](/business/nouns/startup-template/extend?interface=api) | `POST /{namespace}/startup-templates/{startupTemplate}/extend` | [`StartupTemplate.extended`](/business/events/StartupTemplate.extended) | | [StartupTemplate.promote](/business/nouns/startup-template/promote?interface=api) | `POST /{namespace}/startup-templates/{startupTemplate}/promote` | [`StartupTemplate.promoted`](/business/events/StartupTemplate.promoted) | | [StartupTemplate.upgrade](/business/nouns/startup-template/upgrade?interface=api) | `POST /{namespace}/startup-templates/{startupTemplate}/upgrade` | [`StartupTemplate.upgraded`](/business/events/StartupTemplate.upgraded) | ### Statement | Operation | Route | Event | | --- | --- | --- | | [Statement.get](/business/nouns/statement/get?interface=api) | `GET /{namespace}/statements/{id}` | None. | | [Statement.list](/business/nouns/statement/list?interface=api) | `GET /{namespace}/statements` | None. | ### Story | Operation | Route | Event | | --- | --- | --- | | [Story.create](/business/nouns/story/create?interface=api) | `POST /{namespace}/stories` | `Story.created` | | [Story.get](/business/nouns/story/get?interface=api) | `GET /{namespace}/stories/{id}` | None. | | [Story.list](/business/nouns/story/list?interface=api) | `GET /{namespace}/stories` | None. | | [Story.update](/business/nouns/story/update?interface=api) | `PATCH /{namespace}/stories/{id}` | `Story.updated` | | [Story.delete](/business/nouns/story/delete?interface=api) | `DELETE /{namespace}/stories/{id}` | `Story.deleted` | ### Studio | Operation | Route | Event | | --- | --- | --- | | [Studio.create](/business/nouns/studio/create?interface=api) | `POST /{namespace}/studios` | `Studio.created` | | [Studio.get](/business/nouns/studio/get?interface=api) | `GET /{namespace}/studios/{id}` | None. | | [Studio.list](/business/nouns/studio/list?interface=api) | `GET /{namespace}/studios` | None. | | [Studio.update](/business/nouns/studio/update?interface=api) | `PATCH /{namespace}/studios/{id}` | `Studio.updated` | | [Studio.delete](/business/nouns/studio/delete?interface=api) | `DELETE /{namespace}/studios/{id}` | `Studio.deleted` | ### Subscription | Operation | Route | Event | | --- | --- | --- | | [Subscription.create](/business/nouns/subscription/create?interface=api) | `POST /{namespace}/subscriptions` | `Subscription.created` | | [Subscription.get](/business/nouns/subscription/get?interface=api) | `GET /{namespace}/subscriptions/{id}` | None. | | [Subscription.list](/business/nouns/subscription/list?interface=api) | `GET /{namespace}/subscriptions` | None. | | [Subscription.update](/business/nouns/subscription/update?interface=api) | `PATCH /{namespace}/subscriptions/{id}` | `Subscription.updated` | | [Subscription.keep](/business/nouns/subscription/keep?interface=api) | `POST /{namespace}/subscriptions/{subscription}/keep` | [`Subscription.kept`](/business/events/Subscription.kept) | | [Subscription.pause](/business/nouns/subscription/pause?interface=api) | `POST /{namespace}/subscriptions/{subscription}/pause` | [`Subscription.paused`](/business/events/Subscription.paused) | | [Subscription.renew](/business/nouns/subscription/renew?interface=api) | `POST /{namespace}/subscriptions/{subscription}/renew` | [`Subscription.renewed`](/business/events/Subscription.renewed) | | [Subscription.resize](/business/nouns/subscription/resize?interface=api) | `POST /{namespace}/subscriptions/{subscription}/resize` | [`Subscription.resized`](/business/events/Subscription.resized) | | [Subscription.resume](/business/nouns/subscription/resume?interface=api) | `POST /{namespace}/subscriptions/{subscription}/resume` | [`Subscription.resumed`](/business/events/Subscription.resumed) | | [Subscription.switch](/business/nouns/subscription/switch?interface=api) | `POST /{namespace}/subscriptions/{subscription}/switch` | [`Subscription.switched`](/business/events/Subscription.switched) | | [Subscription.unsubscribe](/business/nouns/subscription/unsubscribe?interface=api) | `POST /{namespace}/subscriptions/{subscription}/unsubscribe` | [`Subscription.unsubscribed`](/business/events/Subscription.unsubscribed) | ### Supplier | Operation | Route | Event | | --- | --- | --- | | [Supplier.create](/business/nouns/supplier/create?interface=api) | `POST /{namespace}/suppliers` | `Supplier.created` | | [Supplier.get](/business/nouns/supplier/get?interface=api) | `GET /{namespace}/suppliers/{id}` | None. | | [Supplier.list](/business/nouns/supplier/list?interface=api) | `GET /{namespace}/suppliers` | None. | | [Supplier.update](/business/nouns/supplier/update?interface=api) | `PATCH /{namespace}/suppliers/{id}` | `Supplier.updated` | | [Supplier.delete](/business/nouns/supplier/delete?interface=api) | `DELETE /{namespace}/suppliers/{id}` | `Supplier.deleted` | ### Suppression | Operation | Route | Event | | --- | --- | --- | | [Suppression.create](/business/nouns/suppression/create?interface=api) | `POST /{namespace}/suppressions` | `Suppression.created` | | [Suppression.get](/business/nouns/suppression/get?interface=api) | `GET /{namespace}/suppressions/{id}` | None. | | [Suppression.list](/business/nouns/suppression/list?interface=api) | `GET /{namespace}/suppressions` | None. | ### Survey | Operation | Route | Event | | --- | --- | --- | | [Survey.create](/business/nouns/survey/create?interface=api) | `POST /{namespace}/surveys` | `Survey.created` | | [Survey.get](/business/nouns/survey/get?interface=api) | `GET /{namespace}/surveys/{id}` | None. | | [Survey.list](/business/nouns/survey/list?interface=api) | `GET /{namespace}/surveys` | None. | | [Survey.update](/business/nouns/survey/update?interface=api) | `PATCH /{namespace}/surveys/{id}` | `Survey.updated` | | [Survey.delete](/business/nouns/survey/delete?interface=api) | `DELETE /{namespace}/surveys/{id}` | `Survey.deleted` | ### System | Operation | Route | Event | | --- | --- | --- | | [System.create](/business/nouns/system/create?interface=api) | `POST /{namespace}/systems` | `System.created` | | [System.get](/business/nouns/system/get?interface=api) | `GET /{namespace}/systems/{id}` | None. | | [System.list](/business/nouns/system/list?interface=api) | `GET /{namespace}/systems` | None. | | [System.update](/business/nouns/system/update?interface=api) | `PATCH /{namespace}/systems/{id}` | `System.updated` | | [System.delete](/business/nouns/system/delete?interface=api) | `DELETE /{namespace}/systems/{id}` | `System.deleted` | ### Task | Operation | Route | Event | | --- | --- | --- | | [Task.create](/business/nouns/task/create?interface=api) | `POST /{namespace}/tasks` | `Task.created` | | [Task.get](/business/nouns/task/get?interface=api) | `GET /{namespace}/tasks/{id}` | None. | | [Task.list](/business/nouns/task/list?interface=api) | `GET /{namespace}/tasks` | None. | | [Task.update](/business/nouns/task/update?interface=api) | `PATCH /{namespace}/tasks/{id}` | `Task.updated` | | [Task.delete](/business/nouns/task/delete?interface=api) | `DELETE /{namespace}/tasks/{id}` | `Task.deleted` | | [Task.assign](/business/nouns/task/assign?interface=api) | `POST /{namespace}/tasks/{task}/assign` | [`Task.assigned`](/business/events/Task.assigned) | | [Task.claim](/business/nouns/task/claim?interface=api) | `POST /{namespace}/tasks/{task}/claim` | [`Task.claimed`](/business/events/Task.claimed) | | [Task.complete](/business/nouns/task/complete?interface=api) | `POST /{namespace}/tasks/{task}/complete` | [`Task.completed`](/business/events/Task.completed) | | [Task.delegate](/business/nouns/task/delegate?interface=api) | `POST /{namespace}/tasks/{task}/delegate` | [`Task.delegated`](/business/events/Task.delegated) | | [Task.escalate](/business/nouns/task/escalate?interface=api) | `POST /{namespace}/tasks/{task}/escalate` | [`Task.escalated`](/business/events/Task.escalated) | | [Task.next](/business/nouns/task/next?interface=api) | `POST /{namespace}/tasks/next` | [`Task.offered`](/business/events/Task.offered) | | [Task.return](/business/nouns/task/return?interface=api) | `POST /{namespace}/tasks/{task}/return` | [`Task.returned`](/business/events/Task.returned) | ### Team | Operation | Route | Event | | --- | --- | --- | | [Team.create](/business/nouns/team/create?interface=api) | `POST /{namespace}/teams` | `Team.created` | | [Team.get](/business/nouns/team/get?interface=api) | `GET /{namespace}/teams/{id}` | None. | | [Team.list](/business/nouns/team/list?interface=api) | `GET /{namespace}/teams` | None. | | [Team.update](/business/nouns/team/update?interface=api) | `PATCH /{namespace}/teams/{id}` | `Team.updated` | | [Team.delete](/business/nouns/team/delete?interface=api) | `DELETE /{namespace}/teams/{id}` | `Team.deleted` | ### Template | Operation | Route | Event | | --- | --- | --- | | [Template.create](/business/nouns/template/create?interface=api) | `POST /{namespace}/templates` | `Template.created` | | [Template.get](/business/nouns/template/get?interface=api) | `GET /{namespace}/templates/{id}` | None. | | [Template.list](/business/nouns/template/list?interface=api) | `GET /{namespace}/templates` | None. | | [Template.update](/business/nouns/template/update?interface=api) | `PATCH /{namespace}/templates/{id}` | `Template.updated` | | [Template.delete](/business/nouns/template/delete?interface=api) | `DELETE /{namespace}/templates/{id}` | `Template.deleted` | | [Template.extend](/business/nouns/template/extend?interface=api) | `POST /{namespace}/templates/{template}/extend` | [`Template.extended`](/business/events/Template.extended) | | [Template.promote](/business/nouns/template/promote?interface=api) | `POST /{namespace}/templates/{template}/promote` | [`Template.promoted`](/business/events/Template.promoted) | | [Template.upgrade](/business/nouns/template/upgrade?interface=api) | `POST /{namespace}/templates/{template}/upgrade` | [`Template.upgraded`](/business/events/Template.upgraded) | ### Tenant | Operation | Route | Event | | --- | --- | --- | | [Tenant.create](/business/nouns/tenant/create?interface=api) | `POST /{namespace}/tenants` | `Tenant.created` | | [Tenant.get](/business/nouns/tenant/get?interface=api) | `GET /{namespace}/tenants/{id}` | None. | | [Tenant.list](/business/nouns/tenant/list?interface=api) | `GET /{namespace}/tenants` | None. | | [Tenant.update](/business/nouns/tenant/update?interface=api) | `PATCH /{namespace}/tenants/{id}` | `Tenant.updated` | | [Tenant.delete](/business/nouns/tenant/delete?interface=api) | `DELETE /{namespace}/tenants/{id}` | `Tenant.deleted` | | [Tenant.invite](/business/nouns/tenant/invite?interface=api) | `POST /{namespace}/tenants/{tenant}/invite` | [`Tenant.invited`](/business/events/Tenant.invited) | | [Tenant.pin](/business/nouns/tenant/pin?interface=api) | `POST /{namespace}/tenants/{tenant}/pin` | [`Tenant.pinned`](/business/events/Tenant.pinned) | | [Tenant.provision](/business/nouns/tenant/provision?interface=api) | `POST /{namespace}/tenants/provision` | [`Tenant.provisioned`](/business/events/Tenant.provisioned) | | [Tenant.requestSetup](/business/nouns/tenant/request-setup?interface=api) | `POST /{namespace}/tenants/{tenant}/requestSetup` | [`Tenant.setupRequested`](/business/events/Tenant.setupRequested) | ### Theme | Operation | Route | Event | | --- | --- | --- | | [Theme.create](/business/nouns/theme/create?interface=api) | `POST /{namespace}/themes` | `Theme.created` | | [Theme.get](/business/nouns/theme/get?interface=api) | `GET /{namespace}/themes/{id}` | None. | | [Theme.list](/business/nouns/theme/list?interface=api) | `GET /{namespace}/themes` | None. | | [Theme.update](/business/nouns/theme/update?interface=api) | `PATCH /{namespace}/themes/{id}` | `Theme.updated` | | [Theme.delete](/business/nouns/theme/delete?interface=api) | `DELETE /{namespace}/themes/{id}` | `Theme.deleted` | ### Thing | Operation | Route | Event | | --- | --- | --- | | [Thing.create](/business/nouns/thing/create?interface=api) | `POST /{namespace}/things` | `Thing.created` | | [Thing.get](/business/nouns/thing/get?interface=api) | `GET /{namespace}/things/{id}` | None. | | [Thing.list](/business/nouns/thing/list?interface=api) | `GET /{namespace}/things` | None. | | [Thing.update](/business/nouns/thing/update?interface=api) | `PATCH /{namespace}/things/{id}` | `Thing.updated` | | [Thing.delete](/business/nouns/thing/delete?interface=api) | `DELETE /{namespace}/things/{id}` | `Thing.deleted` | | [Thing.relate](/business/nouns/thing/relate?interface=api) | `POST /{namespace}/things/{thing}/relate` | [`Thing.related`](/business/events/Thing.related) | | [Thing.resolve](/business/nouns/thing/resolve?interface=api) | `POST /{namespace}/things/resolve` | [`Thing.resolved`](/business/events/Thing.resolved) | | [Thing.share](/business/nouns/thing/share?interface=api) | `POST /{namespace}/things/{thing}/share` | [`Thing.shared`](/business/events/Thing.shared) | | [Thing.unrelate](/business/nouns/thing/unrelate?interface=api) | `POST /{namespace}/things/{thing}/unrelate` | [`Thing.unrelated`](/business/events/Thing.unrelated) | ### Thread | Operation | Route | Event | | --- | --- | --- | | [Thread.create](/business/nouns/thread/create?interface=api) | `POST /{namespace}/threads` | `Thread.created` | | [Thread.get](/business/nouns/thread/get?interface=api) | `GET /{namespace}/threads/{id}` | None. | | [Thread.list](/business/nouns/thread/list?interface=api) | `GET /{namespace}/threads` | None. | | [Thread.update](/business/nouns/thread/update?interface=api) | `PATCH /{namespace}/threads/{id}` | `Thread.updated` | | [Thread.delete](/business/nouns/thread/delete?interface=api) | `DELETE /{namespace}/threads/{id}` | `Thread.deleted` | ### Tool | Operation | Route | Event | | --- | --- | --- | | [Tool.create](/business/nouns/tool/create?interface=api) | `POST /{namespace}/tools` | `Tool.created` | | [Tool.get](/business/nouns/tool/get?interface=api) | `GET /{namespace}/tools/{id}` | None. | | [Tool.list](/business/nouns/tool/list?interface=api) | `GET /{namespace}/tools` | None. | | [Tool.update](/business/nouns/tool/update?interface=api) | `PATCH /{namespace}/tools/{id}` | `Tool.updated` | | [Tool.delete](/business/nouns/tool/delete?interface=api) | `DELETE /{namespace}/tools/{id}` | `Tool.deleted` | ### Transaction | Operation | Route | Event | | --- | --- | --- | | [Transaction.get](/business/nouns/transaction/get?interface=api) | `GET /{namespace}/transactions/{id}` | None. | | [Transaction.list](/business/nouns/transaction/list?interface=api) | `GET /{namespace}/transactions` | None. | | [Transaction.attach](/business/nouns/transaction/attach?interface=api) | `POST /{namespace}/transactions/{transaction}/attach` | [`Transaction.attached`](/business/events/Transaction.attached) | | [Transaction.categorize](/business/nouns/transaction/categorize?interface=api) | `POST /{namespace}/transactions/{transaction}/categorize` | [`Transaction.categorized`](/business/events/Transaction.categorized) | | [Transaction.reconcile](/business/nouns/transaction/reconcile?interface=api) | `POST /{namespace}/transactions/{transaction}/reconcile` | [`Transaction.reconciled`](/business/events/Transaction.reconciled) | ### Trigger | Operation | Route | Event | | --- | --- | --- | | [Trigger.create](/business/nouns/trigger/create?interface=api) | `POST /{namespace}/triggers` | `Trigger.created` | | [Trigger.get](/business/nouns/trigger/get?interface=api) | `GET /{namespace}/triggers/{id}` | None. | | [Trigger.list](/business/nouns/trigger/list?interface=api) | `GET /{namespace}/triggers` | None. | | [Trigger.update](/business/nouns/trigger/update?interface=api) | `PATCH /{namespace}/triggers/{id}` | `Trigger.updated` | | [Trigger.delete](/business/nouns/trigger/delete?interface=api) | `DELETE /{namespace}/triggers/{id}` | `Trigger.deleted` | ### Variant | Operation | Route | Event | | --- | --- | --- | | [Variant.create](/business/nouns/variant/create?interface=api) | `POST /{namespace}/variants` | `Variant.created` | | [Variant.get](/business/nouns/variant/get?interface=api) | `GET /{namespace}/variants/{id}` | None. | | [Variant.list](/business/nouns/variant/list?interface=api) | `GET /{namespace}/variants` | None. | | [Variant.update](/business/nouns/variant/update?interface=api) | `PATCH /{namespace}/variants/{id}` | `Variant.updated` | | [Variant.delete](/business/nouns/variant/delete?interface=api) | `DELETE /{namespace}/variants/{id}` | `Variant.deleted` | ### Verb | Operation | Route | Event | | --- | --- | --- | | [Verb.create](/business/nouns/verb/create?interface=api) | `POST /{namespace}/verbs` | `Verb.created` | | [Verb.get](/business/nouns/verb/get?interface=api) | `GET /{namespace}/verbs/{id}` | None. | | [Verb.list](/business/nouns/verb/list?interface=api) | `GET /{namespace}/verbs` | None. | | [Verb.update](/business/nouns/verb/update?interface=api) | `PATCH /{namespace}/verbs/{id}` | `Verb.updated` | | [Verb.delete](/business/nouns/verb/delete?interface=api) | `DELETE /{namespace}/verbs/{id}` | `Verb.deleted` | | [Verb.retire](/business/nouns/verb/retire?interface=api) | `POST /{namespace}/verbs/{verb}/retire` | [`Verb.retired`](/business/events/Verb.retired) | ### Version | Operation | Route | Event | | --- | --- | --- | | [Version.get](/business/nouns/version/get?interface=api) | `GET /{namespace}/versions/{id}` | None. | | [Version.list](/business/nouns/version/list?interface=api) | `GET /{namespace}/versions` | None. | | [Version.deploy](/business/nouns/version/deploy?interface=api) | `POST /{namespace}/versions/{version}/deploy` | [`Version.deployed`](/business/events/Version.deployed) | ### Video | Operation | Route | Event | | --- | --- | --- | | [Video.create](/business/nouns/video/create?interface=api) | `POST /{namespace}/videos` | `Video.created` | | [Video.get](/business/nouns/video/get?interface=api) | `GET /{namespace}/videos/{id}` | None. | | [Video.list](/business/nouns/video/list?interface=api) | `GET /{namespace}/videos` | None. | | [Video.update](/business/nouns/video/update?interface=api) | `PATCH /{namespace}/videos/{id}` | `Video.updated` | | [Video.draft](/business/nouns/video/draft?interface=api) | `POST /{namespace}/videos/draft` | [`Video.drafted`](/business/events/Video.drafted) | | [Video.finalize](/business/nouns/video/finalize?interface=api) | `POST /{namespace}/videos/{video}/finalize` | [`Video.finalized`](/business/events/Video.finalized) | ### Visit | Operation | Route | Event | | --- | --- | --- | | [Visit.get](/business/nouns/visit/get?interface=api) | `GET /{namespace}/visits/{id}` | None. | | [Visit.list](/business/nouns/visit/list?interface=api) | `GET /{namespace}/visits` | None. | ### Visitor | Operation | Route | Event | | --- | --- | --- | | [Visitor.create](/business/nouns/visitor/create?interface=api) | `POST /{namespace}/visitors` | `Visitor.created` | | [Visitor.get](/business/nouns/visitor/get?interface=api) | `GET /{namespace}/visitors/{id}` | None. | | [Visitor.list](/business/nouns/visitor/list?interface=api) | `GET /{namespace}/visitors` | None. | | [Visitor.update](/business/nouns/visitor/update?interface=api) | `PATCH /{namespace}/visitors/{id}` | `Visitor.updated` | | [Visitor.delete](/business/nouns/visitor/delete?interface=api) | `DELETE /{namespace}/visitors/{id}` | `Visitor.deleted` | | [Visitor.forget](/business/nouns/visitor/forget?interface=api) | `POST /{namespace}/visitors/{visitor}/forget` | [`Visitor.forgotten`](/business/events/Visitor.forgotten) | | [Visitor.identify](/business/nouns/visitor/identify?interface=api) | `POST /{namespace}/visitors/{visitor}/identify` | [`Visitor.identified`](/business/events/Visitor.identified) | | [Visitor.merge](/business/nouns/visitor/merge?interface=api) | `POST /{namespace}/visitors/{visitor}/merge` | [`Visitor.merged`](/business/events/Visitor.merged) | ### Voice | Operation | Route | Event | | --- | --- | --- | | [Voice.get](/business/nouns/voice/get?interface=api) | `GET /{namespace}/voices/{id}` | None. | | [Voice.list](/business/nouns/voice/list?interface=api) | `GET /{namespace}/voices` | None. | | [Voice.update](/business/nouns/voice/update?interface=api) | `PATCH /{namespace}/voices/{id}` | `Voice.updated` | | [Voice.clone](/business/nouns/voice/clone?interface=api) | `POST /{namespace}/voices/clone` | [`Voice.cloned`](/business/events/Voice.cloned) | | [Voice.retire](/business/nouns/voice/retire?interface=api) | `POST /{namespace}/voices/{voice}/retire` | [`Voice.retired`](/business/events/Voice.retired) | ### Waitlist | Operation | Route | Event | | --- | --- | --- | | [Waitlist.create](/business/nouns/waitlist/create?interface=api) | `POST /{namespace}/waitlists` | `Waitlist.created` | | [Waitlist.get](/business/nouns/waitlist/get?interface=api) | `GET /{namespace}/waitlists/{id}` | None. | | [Waitlist.list](/business/nouns/waitlist/list?interface=api) | `GET /{namespace}/waitlists` | None. | | [Waitlist.update](/business/nouns/waitlist/update?interface=api) | `PATCH /{namespace}/waitlists/{id}` | `Waitlist.updated` | | [Waitlist.delete](/business/nouns/waitlist/delete?interface=api) | `DELETE /{namespace}/waitlists/{id}` | `Waitlist.deleted` | | [Waitlist.admit](/business/nouns/waitlist/admit?interface=api) | `POST /{namespace}/waitlists/{waitlist}/admit` | [`Waitlist.admitted`](/business/events/Waitlist.admitted) | | [Waitlist.join](/business/nouns/waitlist/join?interface=api) | `POST /{namespace}/waitlists/{waitlist}/join` | [`Waitlist.joined`](/business/events/Waitlist.joined) | ### Watch | Operation | Route | Event | | --- | --- | --- | | [Watch.create](/business/nouns/watch/create?interface=api) | `POST /{namespace}/watches` | `Watch.created` | | [Watch.get](/business/nouns/watch/get?interface=api) | `GET /{namespace}/watches/{id}` | None. | | [Watch.list](/business/nouns/watch/list?interface=api) | `GET /{namespace}/watches` | None. | | [Watch.update](/business/nouns/watch/update?interface=api) | `PATCH /{namespace}/watches/{id}` | `Watch.updated` | | [Watch.delete](/business/nouns/watch/delete?interface=api) | `DELETE /{namespace}/watches/{id}` | `Watch.deleted` | | [Watch.pause](/business/nouns/watch/pause?interface=api) | `POST /{namespace}/watches/{watch}/pause` | [`Watch.paused`](/business/events/Watch.paused) | | [Watch.replay](/business/nouns/watch/replay?interface=api) | `POST /{namespace}/watches/{watch}/replay` | [`Watch.replayed`](/business/events/Watch.replayed) | | [Watch.resume](/business/nouns/watch/resume?interface=api) | `POST /{namespace}/watches/{watch}/resume` | [`Watch.resumed`](/business/events/Watch.resumed) | | [Watch.rotate](/business/nouns/watch/rotate?interface=api) | `POST /{namespace}/watches/{watch}/rotate` | [`Watch.rotated`](/business/events/Watch.rotated) | ### Worker | Operation | Route | Event | | --- | --- | --- | | [Worker.create](/business/nouns/worker/create?interface=api) | `POST /{namespace}/workers` | `Worker.created` | | [Worker.get](/business/nouns/worker/get?interface=api) | `GET /{namespace}/workers/{id}` | None. | | [Worker.list](/business/nouns/worker/list?interface=api) | `GET /{namespace}/workers` | None. | | [Worker.update](/business/nouns/worker/update?interface=api) | `PATCH /{namespace}/workers/{id}` | `Worker.updated` | | [Worker.delete](/business/nouns/worker/delete?interface=api) | `DELETE /{namespace}/workers/{id}` | `Worker.deleted` | ### Workflow | Operation | Route | Event | | --- | --- | --- | | [Workflow.create](/business/nouns/workflow/create?interface=api) | `POST /{namespace}/workflows` | `Workflow.created` | | [Workflow.get](/business/nouns/workflow/get?interface=api) | `GET /{namespace}/workflows/{id}` | None. | | [Workflow.list](/business/nouns/workflow/list?interface=api) | `GET /{namespace}/workflows` | None. | | [Workflow.update](/business/nouns/workflow/update?interface=api) | `PATCH /{namespace}/workflows/{id}` | `Workflow.updated` | | [Workflow.delete](/business/nouns/workflow/delete?interface=api) | `DELETE /{namespace}/workflows/{id}` | `Workflow.deleted` | # API spec URL: /code/api/spec · Id: `page:code/api/spec` > Every rule a client of api.sb can rely on. [api.sb](/code/platform/api-sb) serves every [Startup](/business/nouns/startup) under its namespace, one route per operation, with one JSON envelope on every response. ### Base URL Every Startup has a namespace, its domain. Every route sits under it. ```text https://api.sb/{namespace} https://api.sb/acme.com ``` ### Authentication Send a key as a bearer token. Test keys start with `sk_test_`, live keys with `sk_live_`. A key acts in its own namespace and scopes only. ```bash curl https://api.sb/acme.com/offers \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` ### Routes | Operation | Method | Path | Body | | --- | --- | --- | --- | | create | POST | `/{namespace}/{nouns}` | The properties | | list | GET | `/{namespace}/{nouns}` | Query: `limit`, `after` | | get | GET | `/{namespace}/{nouns}/{id}` | None. | | update | PATCH | `/{namespace}/{nouns}/{id}` | The properties to change | | delete | DELETE | `/{namespace}/{nouns}/{id}` | None. | | A Verb on one record | POST | `/{namespace}/{nouns}/{noun}/{verb}` | The other inputs | | A Verb on the collection | POST | `/{namespace}/{nouns}/{verb}` | The inputs | `{nouns}` is the plural in kebab case. The operationId of every route is its `Noun.verb` name. A body is JSON, sent with `Content-Type: application/json`. Responses are `application/json`; errors are `application/problem+json`. ### Ids A record's `$id` is its URL. Its id is the last segment: `offer_1` in `https://api.sb/acme.com/offers/offer_1`. Every input that names a record takes either form. | Verb | Names its record | Route | | --- | --- | --- | | `get`, `update`, `delete` | `id` | `/{nouns}/{id}` | | Every other Verb | Its Noun in camelCase: `offer`, `payRun` | `/{nouns}/{noun}/{verb}` | When a call uses a record an earlier call returned, it passes the returned id on: `offer.$id` in the SDK and MCP, `jq -r '.offer["$id"] | split("/") | last'` in a shell. ### Deleting `delete` is the one Verb that removes a record, and its history is kept. No Noun has an `archive` Verb. To stop something without removing it, call the Verb that ends it: `Offer.withdraw` closes an Offer to new Customers and keeps every Subscription. ### Modes | Mode | Meaning | Ask for it | | --- | --- | --- | | `try` | The caller waits for the result and nothing is stored. | `?mode=try` | | `send` | The call returns a `pending` Action at once and runs durably. | `?mode=send` | | `do` | The call runs durably and returns when the Action finishes. | `?mode=do` | A `GET` on a Verb route returns its preview, the same as `?mode=try`. Writes default to `do`. A `send` call answers `202` with the `pending` Action. ### Envelope Every response is one JSON object: the result under its own key, plus navigation. | Key | Holds | | --- | --- | | `api` | The namespace URL. | | `$type` | The Noun of the record or list. | | `$id` | The canonical URL of the record. | | ``, `` | The record, or one page of records, under its Noun name. | | `action` | The Action a write ran, with its status. | | `meta` | The page: `limit` and the `after` cursor. | | `links` | Navigation: `self`, `up`, `next`. | | `actions` | The Verbs the caller can run on the record, by URL. | ```json { "api": "https://api.sb/acme.com", "$type": "Offer", "$id": "https://api.sb/acme.com/offers/offer_1", "offer": { "$id": "https://api.sb/acme.com/offers/offer_1", "$type": "Offer", "price": { "amount": 49, "currency": "USD" } }, "links": { "self": "https://api.sb/acme.com/offers/offer_1", "up": "https://api.sb/acme.com/offers" }, "actions": { "accept": "https://api.sb/acme.com/offers/offer_1/accept", "grant": "https://api.sb/acme.com/offers/offer_1/grant", "publish": "https://api.sb/acme.com/offers/offer_1/publish" } } ``` A write returns its Action beside the result: ```json { "api": "https://api.sb/acme.com", "offer": { "$id": "https://api.sb/acme.com/offers/offer_1", "$type": "Offer", "price": { "amount": 49, "currency": "USD" } }, "action": { "$id": "https://api.sb/acme.com/actions/action_1", "operation": "Offer.publish", "status": "done" }, "links": { "self": "https://api.sb/acme.com/actions/action_1" } } ``` ### Pagination A list returns at most `limit` records, newest first. Pass `links.next`, or its `after` cursor, for the next page. ### Idempotency Send an `Idempotency-Key` header on any write. A repeat with the same key returns the first Action and runs nothing. ### Errors Every error is an RFC 9457 problem served as `application/problem+json`. Its `type` is the URL of the error page; `fix` and `next` say what to do. The [error catalog](/code/api/error-catalog) lists them all. ```json { "type": "https://startupbuilder.dev/errors/not-found", "title": "Not found", "status": 404, "detail": "No record, Noun, or Verb exists at the path, or the caller cannot see it.", "fix": "Check the namespace and the id, or search for the record first.", "instance": "https://api.sb/acme.com/actions/action_1" } ``` ### Webhooks Every write emits an Event named `Noun.pastTense`. A webhook receives each delivery as a signed `POST`. The `StartupBuilder-Signature` header holds a timestamp `t` and one or more `v1` signatures, each a hex HMAC-SHA256 of `t`, a dot and the raw body: `t=1792670400,v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd`. The `webhooks` section of openapi.json types every delivery. ```json { "$id": "https://api.sb/acme.com/events/event_1", "$type": "Event", "name": "Offer.published", "at": "2026-10-22T12:00:00Z", "seq": 1, "data": { "offer": { "$id": "https://api.sb/acme.com/offers/offer_1", "$type": "Offer", "price": { "amount": 49, "currency": "USD" } } } } ``` ### OpenAPI The whole API as one OpenAPI 3.1 document: [openapi.json](https://startupbuilder.dev/openapi.json). Each Startup also serves its own at `https://api.sb/acme.com/openapi.json`. # Build with a coding agent URL: /code/build-with-a-coding-agent · Id: `page:code/build-with-a-coding-agent` > Point a coding agent at a Startup project with its briefing file, two MCP servers, a scoped test key and the Change loop. `npm create startups` writes `AGENTS.md` and `.mcp.json`, so a coding [Agent](/business/nouns/agent) works the [Startup](/business/nouns/startup) from its first prompt. The agent edits files, calls [Verbs](/business/nouns/verb) and ships through [Changes](/business/nouns/change), never around them. ## Prerequisites - A project from `npm create startups`. The examples use `leaseline.app`, which tracks lease renewals for small property managers at $29 a month. - A coding agent that reads `AGENTS.md` and connects to MCP servers over streamable HTTP. ## Steps 1. Read the `AGENTS.md` the project ships. It is the agent's whole briefing, and you edit it freely: ```md title="AGENTS.md" # Leaseline This repository defines Leaseline. Its files compile into the running business. ## Before you write - Connect both MCP servers in .mcp.json. - Fetch /$.d.ts from the leaseline server: the types of $, cut to your key. - Read the convention for a file before you change it: https://startupbuilder.dev/code/file-conventions ## While you work - Keep npx startup-builder dev running. Each save previews as a Change. - Print a Verb's input with npx startup-builder schema before you call it. - Rehearse every write with --try, or mode "try" in the do tool. ## Never - Never edit generated/ or .sb/. Name secrets in env.ts; never write a value. - Never call Stripe or any outside API directly. Call the Verb. - Never use --env live. Shipping is Change.review, then the founder's Version.deploy. ``` 2. Check `.mcp.json`. It connects two servers: the Startup itself on [api.sb](/code/platform/api-sb), and these docs: ```json title=".mcp.json" { "mcpServers": { "leaseline": { "url": "https://api.sb/mcp?ns=leaseline.app" }, "startupbuilder-docs": { "url": "https://startupbuilder.dev/mcp" } } } ``` The first acts on the business through `search`, `fetch` and `do` ([MCP](/code/mcp)). The second reads documentation and needs no key ([docs for agents](/start/docs-for-agents)). 3. Give the agent its own test key, scoped to the Verbs it needs and expiring on its own: ```bash npx startup-builder keys create --name coding-agent --scope leaseline.app --verbs Offer.publish,Change.review --expire-in 30d ``` Set it as `STARTUP_BUILDER_API_KEY` in the agent's shell. A test key never touches live data or real money ([keys](/code/api/guides/keys)). 4. Start the dev server in a second terminal, so every edit compiles and previews: ```bash npx startup-builder dev ``` 5. Ask for a change in plain words, such as "add a 60-day notice field to leases". The agent edits `nouns/Lease.mdx`, the dev server recompiles, and a broken convention fails with the file and line. 6. When the preview is right, have the agent review the Change. Every test and [Evaluator](/business/nouns/evaluator) runs on the preview: **Ask** ```text Review my change. ``` **API** ```bash curl -X POST https://api.sb/leaseline.app/changes/change_1/review \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" ``` **SDK** ```ts import { $ } from 'startup-builder' const change = await $.Change.review({ change: 'change_1' }) ``` **CLI** ```bash npx startup-builder do Change.review --json '{"change":"change_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Change.review({ change: 'change_1' })" } } ``` 7. Merge and deploy the Change. [Ship my changes](/code/ship-my-changes) shows the calls; `Version.deploy` asks the founder first, so the agent never ships to customers alone. ## Result The agent edits files, checks each call against the types before it runs, and ships only reviewed Changes. A write over the key's [Limit](/business/nouns/limit) waits `pending` for an [Approval](/business/nouns/approval) instead of failing. An agent offers only what these docs document. The founder's words map to guides in [/asks.json](/asks.json); anything not documented, the agent does not offer. ## Next steps - [Every file convention](/code/file-conventions): what the agent writes, file by file. - [MCP](/code/mcp): `search`, `fetch` and `do` on a Startup. - [Run the CLI in CI](/code/cli/guides/ci): the same checks on every pull request. # Builders as compilers URL: /code/builders · Id: `page:code/builders` > How a Startup project compiles into a running business, which Builder owns each folder, and how to trace any value to its file. A [Builder](/business/nouns/builder) compiles part of a project into the running business. [StartupBuilder](/code/builders/startup) directs four others, and each owns a set of folders. ## Five Builders | Builder | Compiles | Produces | | --- | --- | --- | | StartupBuilder | `startup.ts`, `startups.lock`, `settings.mdx`, `policies.mdx`, `agents/`, `workflows/`, `plays/`, `systems/`, `dashboards/`, `tests/` | The [Startup](/business/nouns/startup), [Teams](/business/nouns/team), [Roles](/business/nouns/role), [Processes](/business/nouns/process), [Workflows](/business/nouns/workflow), [Dashboards](/business/nouns/dashboard) | | SoftwareBuilder | `nouns/`, `verbs/`, `evaluators/`, `mappings/`, `env.ts`, `products/` of kind [App](/business/nouns/app), API, [Agent](/business/nouns/agent) or [Dataset](/business/nouns/dataset), `apps/`, `code/` | [Nouns](/business/nouns/noun), [Verbs](/business/nouns/verb), [Functions](/business/nouns/function), [Apps](/business/nouns/app), the API, SDK, CLI and MCP | | SiteBuilder | `sites/`, `domains/`, `content/`, `brand/`, `components/` | [Sites](/business/nouns/site), [Pages](/business/nouns/page), [Domains](/business/nouns/domain), [Brand](/business/nouns/brand), [Components](/business/nouns/component) | | [Service](/business/nouns/service)Builder | `products/` of kind [Service](/business/nouns/service), and the outcome terms in its [Offer](/business/nouns/offer) | [Services](/business/nouns/service) and their work lifecycle | | SalesBuilder | `offers/`, demand `plays/` | [Offers](/business/nouns/offer), [Prices](/business/nouns/price), checkout, Stripe [Products](/business/nouns/product) and Prices | ## One compile Every save under `npx startup-builder dev`, and every push, runs the same steps: 1. **Parse.** Each file becomes a typed record. A syntax error, a secret-shaped value or a key set twice stops here and names the line. 2. **Canonicalize.** The record is printed in one canonical form and fingerprinted. Formatting changes mint nothing. 3. **Resolve.** Own values merge over the pinned [Startup Template](/business/nouns/startup-template) into `.sb/resolved/`. 4. **Build.** Each Builder compiles its folders: types, routes, screens, Pages, Stripe objects, MCP tools. 5. **Check.** Verb tests, Role tests, scenario tests and [Evaluators](/business/nouns/evaluator) run on the preview. 6. **Preview.** The result is a [Change](/business/nouns/change) on its own preview address, merged with `Change.merge` and deployed with `Version.deploy`. ## What a compile produces One `nouns/Lease.mdx` file, in a Startup that declares a `Lease` Noun, yields every one of these: | Output | Where | | --- | --- | | Types | `.sb/types/Lease`, and `/$.d.ts` for agents | | API | `GET /leaseline.app/leases`, `POST /leaseline.app/leases/{lease}/renew` | | SDK | `$.Lease.renew({ lease })` | | CLI | `npx startup-builder do Lease.renew --json '{"lease":"lease_1"}'` | | MCP | `Lease.renew` in the `do` tool's program | | App | `/app/leases`, and a form for each Verb | | [Events](/business/nouns/event) | `Lease.created`, `Lease.renewed` | | Docs | A reference page for the Noun and each Verb | ## Reading the output To see where any value came from, show it: ```bash npx startup-builder show /offers/pro/price ``` ```text offers/pro.price = $29 per month set by offers/pro.mdx:3 shadows solo-saas@7 ($19 per month) ``` # SalesBuilder URL: /code/builders/sales · Id: `product:sales-builder` > SalesBuilder finds, wins, and keeps the Customers of a Startup through its Offers. SalesBuilder finds, wins, and keeps the [Customers](/business/nouns/customer) of a [Startup](/business/nouns/startup) through its [Offers](/business/nouns/offer). It runs from the first published [Price](/business/nouns/price) to the renewal of the thousandth [Subscription](/business/nouns/subscription). ## What it does - Finds demand with [Plays](/business/nouns/play) rated on scalability, cost, and latency: seed Plays first, compounding Plays after, inside a demand budget that starts at $0. - Takes refundable deposits on a reserve page before the [Product](/business/nouns/product) exists, the commitment-grade [Evidence](/business/nouns/evidence) that opens Building. - Compiles each Product into Offers and Prices from the founding [Hypothesis](/business/nouns/hypothesis), each line tagged with the slot it came from. - Tests copy and packaging as [Experiments](/business/nouns/experiment), and tests a Price by sibling Offer, market, or switchback, never by showing two buyers two Prices. - Earns by subscription, usage, commerce, marketplace, or directory, with every payment moving through Stripe. - Sells self-serve, carries larger buyers through a [Deal](/business/nouns/deal) to a signed [Quote](/business/nouns/quote), and sends outbound as the Startup or for a person under a [Mandate](/business/nouns/mandate). - Sells to [Agents](/business/nouns/agent): machine registers at Live, a quote before every charge, and a [402 reply](/code/api/errors/payment-required) that names the Offer to accept. - Holds one record per [Person](/business/nouns/person) from the first [Visit](/business/nouns/visit) to renewal, and reads [Consent](/business/nouns/consent) and [Suppression](/business/nouns/suppression) before every [Message](/business/nouns/message). ## Built from - [Offer](/business/nouns/offer) - [Customer](/business/nouns/customer) - [api.sb](/code/platform/api-sb) ## Surfaces - The reserve page, pricing page, checkout, and Customer portal on the Startup's [Site](/business/nouns/site), built by [SiteBuilder](/code/builders/site). - The machine registers every Agent buyer reads: OpenAPI, llms.txt, agents.json, and the MCP server. - The [Sales Team](/agents/sales), whose role agents run each [Process](/business/nouns/process) named here. - The [demand Play catalog](/workflows/plays), run by the [Marketing Team](/agents/marketing), and one page per [Motion](/business/nouns/motion) under [motions](/business/motions). Every [Interface](/business/nouns/interface) calls the same operations. Accepting an Offer: **Ask** ```text Accept the offer “Grain-free kibble, 12 lb”. ``` **API** ```bash curl -X POST https://api.sb/petpantry.shop/offers/offer_1/accept \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"party":"Lena Fischer"}' ``` ```json { "api": "https://api.sb/petpantry.shop", "customer": { "$id": "https://api.sb/petpantry.shop/customers/customer_1", "$type": "Customer", "since": "2026-10-22T12:00:00Z" }, "offer": { "$id": "https://api.sb/petpantry.shop/offers/offer_1", "$type": "Offer", "price": { "amount": 54, "currency": "USD" } }, "action": { "$id": "https://api.sb/petpantry.shop/actions/action_1", "operation": "Offer.accept", "status": "done" }, "links": { "self": "https://api.sb/petpantry.shop/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { customer, offer } = await $.Offer.accept({ offer: 'offer_1', party: 'Lena Fischer' }) ``` **CLI** ```bash npx startup-builder do Offer.accept --json '{"offer":"offer_1","party":"Lena Fischer"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Offer.accept({ offer: 'offer_1', party: 'Lena Fischer' })" } } ``` | Term | Kind | Definition | | --- | --- | --- | | [SalesBuilder](/code/builders/sales) | Product | SalesBuilder finds, wins, and keeps the Customers of a Startup through its Offers. | | [startups.new](/start/startups-new) | Product | startups.new creates a Startup from one sentence and opens it in startups.studio. | | [Customer Team](/agents/customer) | Team | The Customer Team serves every Customer after the first acceptance: onboarding, support, retention, and the one Thread each Person has. | | [Finance Team](/agents/finance) | Team | The Finance Team moves and records the money: Invoices, dunning, refunds within a Limit, payouts, the monthly close, tax, and runway. | | [Marketing Team](/agents/marketing) | Team | The Marketing Team creates and harvests demand: the Brand story, launches, Content, Experiments, and the Metrics the whole Startup reads. | | [Sales Team](/agents/sales) | Team | The Sales Team turns demand into Customers: it answers every Lead, wins enterprise Deals, and runs outbound prospecting. | | [Building](/business/lifecycle/states/building) | Lifecycle state | Building is the state of a Startup whose Agents build its Brand, Products, Offers, site, API, and MCP server from its template. | | [Live](/business/lifecycle/states/live) | Lifecycle state | Live is the state of a Startup that is publicly reachable and takes money from Customers for at least one Offer. | | [Repeatable](/business/lifecycle/states/repeatable) | Lifecycle state | Repeatable is the state of a Startup whose Customers arrive, pay, and stay, while its work runs without its founder. | | [Scale](/business/lifecycle/states/scale) | Lifecycle state | Scale is the state of a Startup that compounds: Customers stay and expand, demand comes from several sources, and margins hold. | | [Autonomous storefront](/start/templates/autonomous-storefront) | Startup Template | An Autonomous storefront runs with no humans and sells physical goods as a Dropship store to people and the Agents that shop for them. | | [Founder-led marketplace](/start/templates/founder-marketplace) | Startup Template | A Founder-led marketplace has one Human founder who signs for a Marketplace, while Agents recruit Suppliers and serve buyers. | | [Dropship store](/products/templates/dropship-store) | Product Template | A Dropship store sells physical goods from a catalog while an upstream holds the stock and ships each Order, with tracking passed through. | | [Licensed-human marketplace](/products/templates/licensed-marketplace) | Product Template | A Licensed-human marketplace matches buyers with credentialed professionals and adds recruiting, Credential checks, and an App where they take work. | | [Marketplace](/products/templates/marketplace) | Product Template | A Marketplace matches buyers with Suppliers who deal with each other directly, and earns a take rate on every transaction it settles. | | [Ads](/systems/ads) | System | Ads places paid and house Ads for Offers to Audiences within Campaign budgets and attributes the conversions they earn. | | [Agreements](/systems/agreements) | System | Agreements drafts each Agreement between two or more Parties from Templates, routes it for signature, records who signed, and tracks its term and economics. | | [Billing](/systems/billing) | System | Billing turns accepted Offers into Orders, Subscriptions, Invoices, metered usage and Entitlements on Stripe, with checkout and dunning. | | [Commerce](/systems/commerce) | System | Commerce is the opt-in System for Startups that sell physical goods by dropship: catalog, Orders, upstream fulfillment and shipment tracking. | | [CRM](/systems/crm) | System | CRM keeps the Contacts and Organizations a Startup knows, every Lead, and the Deals it pursues with them. | | [Earnings](/systems/payouts) | System | Earnings pays Suppliers, Partners and affiliates their earnings through Stripe, holds disputed amounts, and sends statements and year-end tax filings. | | [Matchmaking](/systems/matching) | System | Matchmaking pairs buyers with Suppliers’ Offers, records the merchant of record on each Order, and takes the Startup’s fee through Stripe. | | [Media production](/systems/media) | System | Media production makes a Startup’s Videos, images and voice from its records: drafted, generated, rendered per format, checked, then finalized for publishing. | | [Prospecting](/systems/prospecting) | System | Prospecting finds Prospects who have never engaged, verifies how to reach each one, and records the legal basis for contacting them. | | [Quotes](/systems/quotes) | System | Quotes drafts priced proposals of one or more Offers to one buyer within Limits and turns each accepted Quote into an Order. | | [Referrals](/systems/referrals) | System | Referrals records each Contact, Customer or Partner sending a Lead or Customer to a Startup, and pays the reward its Agreement promises. | | [Reviews](/systems/reviews) | System | Reviews shows each Person’s evaluation of a Product, Offer or Brand where evaluations are shown, requested, moderated and mirrored from elsewhere. | | [Scheduling](/systems/scheduling) | System | Scheduling books Meetings between Workers and Contacts from shared availability and keeps the notes, Decisions and Tasks they produce. | | [Sequences](/systems/sequences) | System | Sequences runs timed, branching series of Messages and Tasks for one Contact at a time, inside designed Funnels. | | [Social](/systems/social) | System | Social publishes posts from a Startup’s own accounts on a calendar and collects the replies and mentions they draw. | | [Success](/systems/success) | System | Success moves each Customer to value and keeps them: onboarding checklists, health scores, renewals, saves and win-backs. | | [Trust and safety](/systems/trust-safety) | System | Trust and safety screens accounts, posts and Transactions for fraud and abuse, and acts on each report by stated rules. | | [Waitlists](/systems/waitlists) | System | Waitlists holds the Leads waiting for an Offer that is not open to them and invites them ranked as a Setting chooses. | | [Webinars](/systems/webinars) | System | Webinars runs the webinars and meetups Contacts attend, online or in person: invitations, registrations, attendance and follow-up. | | [Billing](/workflows/processes/billing) | Process | Billing charges each Invoice when it is owed, recovers failed payments, and refunds within Limits. | | [Experimentation](/workflows/processes/experimentation) | Process | Experimentation tests one change against a control, with the threshold fixed before the start. | | [Inbound sales](/workflows/processes/inbound-sales) | Process | Inbound sales answers every Lead in writing at once and carries the buyer to a signed Agreement. | | [Launches](/workflows/processes/launches) | Process | Launches tell the right Audiences a Startup is live, where those Audiences already look. | | [Outbound](/workflows/processes/outbound) | Process | Outbound reaches Prospects who match the ICP, with a legal basis for contact and within the touch Limit. | | [Pricing](/workflows/processes/pricing) | Process | Pricing sets each Offer’s model, value metric, and Price, and changes Prices for new buyers only. | | [Quoting](/workflows/processes/quoting) | Process | Quoting prices each Deal from list Price, inside the discount Limit, with terms ready to sign. | | [Retention](/workflows/processes/retention) | Process | Retention keeps Customers by catching silence early, saving once, and winning back once. | | [Answer supplier checks](/workflows/processes/vendor-onboarding/answer-supplier-checks) | Workflow | Answer supplier checks answers a business Customer’s supplier requirements from the record and tracks each one until it is accepted. | | [Compile the demand kit](/workflows/processes/launches/compile-demand-kit) | Workflow | Compile the demand kit emits every asset the demand Plays read before the first one runs, each tagged with its lineage. | | [Fan out an outcome](/workflows/processes/retention/fan-out-outcome) | Workflow | Fan out an outcome turns one confirmed Customer outcome into a dated number, and with Consent into a case study, quote and referral invite. | | [Invoice reminders](/workflows/processes/billing/invoice-reminders) | Workflow | Invoice reminders tell each Customer about a `send` Invoice before its due date and once past it, and never retry a charge. | | [Agent registries](/workflows/plays/agent-registries) | Play | Agent registries list every Startup’s tools where Agents and developers search, with tool descriptions tested against agent tool search. | | [Agent-to-agent selling](/workflows/plays/agent-to-agent) | Play | Agent-to-agent selling lets an unknown Agent discover a Startup, get a quote and pay per call, with no signup and a spend Limit. | | [Answer engine optimization](/workflows/plays/aeo) | Play | Answer engine optimization makes a Startup the cited source when answer engines respond to a Customer’s question, with a dated fact on every Page. | | [Buying committee](/workflows/plays/buying-committee) | Play | Buying committee reaches every member of a named Organization’s buying committee through company-grain Ads, outbound and the Sales Team. | | [Category hubs](/workflows/plays/category-hubs) | Play | Category hubs are owned directories that rank every product in a category by one published rule and route each Visitor to the best fit. | | [Category kit](/workflows/plays/category-kit) | Play | Category kit names the Problem a market does not search for yet, defines it for answer engines, and launches it on one dated day. | | [Cold email](/workflows/plays/cold-email) | Play | Cold email sends short Sequences to Prospects chosen by a dated signal, from secondary Domains, and pauses when complaints pass 0.1 percent. | | [Commission partners](/workflows/plays/commission-partners) | Play | Commission partners pay publishers, creators and Agents a share of the collected, net-of-refund revenue they bring, after the refund window. | | [Community answers](/workflows/plays/community-answers) | Play | Community answers solve questions where Customers already ask them, disclose affiliation, and post as an Agent only where the community allows Agents. | | [Creator ads](/workflows/plays/creator-ads) | Play | Creator ads promote a creator’s winning post as a paid Ad under partnership rights, at or above the minimum effective budget. | | [Creator partnership](/workflows/plays/creator-partnership) | Play | Creator partnership signs creators on one ladder, from referral terms to paid post, co-branded Offer and cofounder, each paid on attributed collected revenue. | | [Creator probe](/workflows/plays/creator-probe) | Play | Creator probe pays five to ten small creators $50 to $500 each for one post, each post a pre-registered arm of one Experiment. | | [Customer referrals](/workflows/plays/customer-referrals) | Play | Customer referrals invite a Customer’s peers after a delivered outcome and pay the reward only on the peer’s paid, unrefunded Order. | | [Data stories](/workflows/plays/data-stories) | Play | Data stories pitch original data to journalists and researchers, scored by mentions on the domains answer engines cite. | | [Developer relations](/workflows/plays/developer-relations) | Play | Developer relations publishes examples, docs and answers that get a developer or Agent to a first successful call within five minutes. | | [Directory listings](/workflows/plays/directory-listings) | Play | Directory listings keep a Startup listed and accurate on review sites, business profiles and vertical directories, free from the day it is Live. | | [Editorial SEO](/workflows/plays/editorial-seo) | Play | Editorial SEO publishes guides, comparisons and alternative Pages that rank for searches a market already makes, refreshed on a fixed cadence or pruned. | | [Engagement bridge](/workflows/plays/engagement-bridge) | Play | Engagement bridge answers public questions from disclosed agent accounts and sends a direct Message only to a Person who engaged, quoting that act. | | [Events and webinars](/workflows/plays/events-and-webinars) | Play | Events and webinars host sessions for mid-market and enterprise Customers, turn each into on-demand content, and enroll attendees in a Sequence within a day. | | [Founder voice](/workflows/plays/founder-voice) | Play | Founder voice posts on a human founder’s own LinkedIn and X under a posting Mandate, each post drafted from the record and approved. | | [Free tools](/workflows/plays/free-tools) | Play | Free tools ship every read-only Verb with a one-field input as a no-signup tool, a citable Page and a free MCP tool. | | [House ads](/workflows/plays/house-ads) | Play | House ads show sibling Startups on the Portfolio’s own Sites, docs and receipts when relevance beats the host Page’s own conversion value. | | [Integration partners](/workflows/plays/integration-partners) | Play | Integration partners ship an integration with a product the Customer already uses, then list it and share Leads under a referral Agreement. | | [Launch sites](/workflows/plays/launch-sites) | Play | Launch sites post a one-day launch that buys a dated record and a backlink, by default as one collection launch per template. | | [Launch week](/workflows/plays/launch-week) | Play | Launch week batches a quarter’s tier 1 and tier 2 Changes into five dated days of posts, Pages, listing refreshes and newsletters. | | [Lead nurture](/workflows/plays/lead-nurture) | Play | Lead nurture enrolls each Lead who has not bought in a Sequence keyed to what they do, ending at purchase, reply or 90 silent days. | | [LinkedIn outbound](/workflows/plays/linkedin-outbound) | Play | LinkedIn outbound sends connection requests and Messages from a Human’s own LinkedIn profile under a Mandate, with Agents researching and drafting. | | [Made with](/workflows/plays/made-with) | Play | Made with puts a disclosed, coded line naming the Startup’s Brand on every output a Customer sends to someone who is not one. | | [Marketplace listings](/workflows/plays/marketplace-listings) | Play | Marketplace listings put a Product in app stores and cloud marketplaces and request reviews only after a Customer’s first success. | | [Open source](/workflows/plays/open-source) | Play | Open source publishes the SDK and integration layer as open repositories, keeps the hosted Product paid, and answers every issue within 48 hours. | | [Organic social](/workflows/plays/organic-social) | Play | Organic social turns facts and artifacts a Startup already has into posts from its disclosed agent accounts and the Studio’s shared accounts. | | [Outbound calling](/workflows/plays/outbound-calling) | Play | Outbound calling phones local and small Organizations, using a voice Agent only where Consent is recorded and a Human where law requires one. | | [Owned newsletter](/workflows/plays/owned-newsletter) | Play | Owned newsletter grows a subscribed list with one fact and one Offer per issue, and suppresses subscribers silent for 90 days. | | [Paid search](/workflows/plays/paid-search) | Play | Paid search bids on Keywords that state intent and runs only while the first transaction’s margin exceeds its cost per first transaction. | | [Paid social](/workflows/plays/paid-social) | Play | Paid social runs Ads targeted by Audience instead of query, first as a pooled test and at scale only for messages that already won. | | [Portfolio cross-sell](/workflows/plays/cross-sell) | Play | Portfolio cross-sell offers sibling Startups inside the Product and the bill, and routes each misfit Lead, with Consent, to the sibling that fits. | | [Positioning tournament](/workflows/plays/positioning-tournament) | Play | Positioning tournament tests head-to-head, subcategory and new-category positionings as arms of one Experiment and writes the winner to the Story. | | [Product-led growth](/workflows/plays/product-led) | Play | Product-led growth gives away a metered slice of a digital Product, a free tool or templates, and prompts the upgrade on a usage event. | | [Programmatic SEO](/workflows/plays/programmatic-seo) | Play | Programmatic SEO generates one Page per entity, place, comparison or question from structured data, and indexes only Pages that carry a unique fact. | | [Promote winners](/workflows/plays/promote-winners) | Play | Promote winners moves a message that won on free placements to a paid Ad with a Hypothesis, a stop rule and the minimum budget. | | [Reserve drop](/workflows/plays/reserve-drop) | Play | Reserve drop opens refundable deposits for 72 hours after one creator post and moves the Startup to Building only if deposits cross the entry check. | | [Retargeting](/workflows/plays/retargeting) | Play | Retargeting shows Ads only to an owned Audience of past Visitors, capped at three impressions per Person per day. | | [Review requests](/workflows/plays/review-requests) | Play | Review requests ask each Customer for a review at a delivered outcome, on the venue the Startup most needs, and show consented reviews. | | [Signal expansion](/workflows/customer/plays/signal-expansion) | Play | Signal expansion turns a Customer’s hiring or a champion’s job change into an expansion Offer, a save, or a warm Sequence at the new Organization. | | [Sponsorships](/workflows/plays/sponsorships) | Play | Sponsorships buy one placement in a newsletter, podcast or channel the ICP already reads, with a coded link, rebooked only on measured payback. | | [Switch kit](/workflows/plays/switch-kit) | Play | Switch kit wins a named rival’s Customers with versus Pages, an importer, a switching Offer, rival-term Ads and outbound to its users. | | [Video ladder](/workflows/plays/video-ladder) | Play | Video ladder renders fact-bound video in every format, screens each cut on organic posts, and promotes only winners to paid Ads. | | [Acquisition](/business/nouns/acquisition) | Noun | An Acquisition is how a Visitor or Prospect first arrived, recorded on its first Event: the referrer kind, the Play, the campaign, and the medium. | | [Ad](/business/nouns/ad) | Noun | An Ad is one paid or house placement promoting an Offer to an Audience, in a format such as search, display, or video. | | [Audience](/business/nouns/audience) | Noun | An Audience is a saved query over Visitors, Leads, Prospects, or Customers, used to target Ads and Messages. | | [Builder](/business/nouns/builder) | Noun | A Builder is a named part of api.sb that builds one side of a Startup; StartupBuilder directs SiteBuilder, SoftwareBuilder, ServiceBuilder, and SalesBuilder. | | [Campaign](/business/nouns/campaign) | Noun | A Campaign is a bounded effort toward a Goal, with a budget, a window, and the Ads or Messages it sends to Audiences. | | [Commission](/business/nouns/commission) | Noun | A Commission is what a Partner earns on the collected revenue its Referral brings, at a rate over a term, paid after a clawback window. | | [Contact](/business/nouns/contact) | Noun | A Contact is a person or Agent a Startup knows by at least one address, where Consent to message them is recorded. | | [Credit Grant](/business/nouns/credit-grant) | Noun | A Credit Grant is a prepaid or promotional balance a Customer spends on a Startup’s metered Offers, checked before each call. | | [Deal](/business/nouns/deal) | Noun | A Deal is a Startup’s pursuit of one buyer’s acceptance of one or more Offers, ending won or lost. | | [Demand Budget](/business/nouns/demand-budget) | Noun | A Demand Budget is the money a founder commits each month to demand Plays, recorded as a Decision with a target and a stop rule. | | [Dispute](/business/nouns/dispute) | Noun | A Dispute is a contested payment or delivery, such as a chargeback, a rejected Service outcome, or a buyer’s claim against a Supplier. | | [Enrollment](/business/nouns/enrollment) | Noun | An Enrollment is one person’s run through one Sequence: the current step, when the next fires, the branches taken, and why it ended. | | [Entitlement](/business/nouns/entitlement) | Noun | An Entitlement is what a Customer gets from an accepted Offer: a Verb on a Noun in its Tenant, optionally bounded by a Limit. | | [Experiment](/business/nouns/experiment) | Noun | An Experiment is a test of a Hypothesis that varies copy or behavior through Flags and judges the variants by a primary Metric. | | [Funnel](/business/nouns/funnel) | Noun | A Funnel is a designed path to an Offer: a landing Page, an opt-in that makes a Lead, a Sequence, then the Offer. | | [Gathering](/business/nouns/gathering) | Noun | A Gathering is a scheduled session many people attend at once, such as a webinar, a workshop, or a launch call, hosted by a Startup. | | [Handle](/business/nouns/handle) | Noun | A Handle is an account or name a Startup or Brand holds on an outside platform, bound to an Integration credential. | | [ICP](/business/nouns/icp) | Noun | An ICP is the ideal customer profile a Startup is built to win: who they are and what they do. | | [Invoice](/business/nouns/invoice) | Noun | An Invoice is what a Customer owes for one or more Offers over one billing period. | | [Keyword](/business/nouns/keyword) | Noun | A Keyword is a search phrase or AI prompt that Pages target, with its rank and citations observed over time. | | [Lead](/business/nouns/lead) | Noun | A Lead is a Contact who raised a hand, by joining a Waitlist, filling a Form, or replying, without accepting an Offer. | | [Meeting](/business/nouns/meeting) | Noun | A Meeting is a scheduled time when Workers and Contacts meet about one or more Things, producing notes, Decisions, and Tasks. | | [Motion](/business/nouns/motion) | Noun | A Motion is the shape of a sale: who buys an Offer and who acts for them, such as b2b, b2c, b2d, b2a, or b2a2b. | | [Order](/business/nouns/order) | Noun | An Order is a Customer’s commitment to buy one or more Offers once, moving from placed to paid, fulfilled, and closed. | | [Organization](/business/nouns/organization) | Noun | An Organization is an outside party as one Startup knows it, keyed by its domain, such as an employer or a vendor. | | [Partner](/business/nouns/partner) | Noun | A Partner is an outside Organization that is party to an Agreement with a Startup, supplying it, distributing its Offers, or both. | | [Persona](/business/nouns/persona) | Noun | A Persona is a named type of person with a job to do, such as a buyer, a seller, or an admin of an App. | | [Play](/business/nouns/play) | Noun | A Play is a named, repeatable strategy with the Metric it moves and its cost, run by a Startup as a Process. | | [Play Mix](/business/nouns/play-mix) | Noun | A Play Mix is the set of Plays a Startup runs this week, each with its state, budget and stop rule, compiled weekly and versioned. | | [Post](/business/nouns/post) | Noun | A Post is something a Handle publishes, such as a thread or a short video, with the reach and replies it earns. | | [Price](/business/nouns/price) | Noun | A Price is the amount, currency, unit, and tiers of an Offer, embedded in it; zero is a Price. | | [Product Template](/business/nouns/product-template) | Noun | A Product Template is a reusable definition of one kind of Product: what it sells, who supplies the work, who buys, and how it earns. | | [Prospect](/business/nouns/prospect) | Noun | A Prospect is a person or Organization a Startup found but who has never engaged, held with the legal basis for contact. | | [Quote](/business/nouns/quote) | Noun | A Quote is a priced proposal of one or more Offers to one buyer, valid until a date, accepted into an Order. | | [Referral](/business/nouns/referral) | Noun | A Referral is a Contact, Customer, or Partner sending a Lead to a Startup, with any reward it earns. | | [Registration](/business/nouns/registration) | Noun | A Registration is one person’s place at a Gathering: invited, requested, or waitlisted, then registered, then attended or no-show. | | [Renewal](/business/nouns/renewal) | Noun | A Renewal is the Deal for a term Subscription’s next term, opened before the term ends and closed renewed, expanded, contracted, or churned. | | [Sequence](/business/nouns/sequence) | Noun | A Sequence is a timed series of steps run for one Contact at a time: send a Message, wait, branch, or stop. | | [Subscription](/business/nouns/subscription) | Noun | A Subscription is a Customer’s standing acceptance of an Offer, billed each Period until canceled. | | [Survey](/business/nouns/survey) | Noun | A Survey is a Form sent to measure, such as NPS or CSAT, whose answers become Metrics and Evidence. | | [Video](/business/nouns/video) | Noun | A Video is a timed composition held as data: a timeline of scenes and spoken lines, drafted from records and rendered per format. | | [Visitor](/business/nouns/visitor) | Noun | A Visitor is someone a Startup cannot name, known by an id scoped to that Startup. | | [Waitlist](/business/nouns/waitlist) | Noun | A Waitlist is the Leads waiting for an Offer that is not open to them, invited in the order a Setting chooses. | | [Contact.enrich](/business/nouns/contact/enrich) | Verb | Enrich fills a Contact’s missing fields from outside sources and marks each value with where it came from. | | [Contact.enroll](/business/nouns/contact/enroll) | Verb | Enroll adds a Contact to a Sequence, which sends its steps until the Contact replies or exits. | | [Customer.exempt](/business/nouns/customer/exempt) | Verb | Exempt records a Customer’s exemption or resale certificate, verifies it, and stops tax on its Orders where the certificate applies. | | [Deal.lose](/business/nouns/deal/lose) | Verb | Lose closes a Deal as lost and records the reason the buyer gave. | | [Deal.propose](/business/nouns/deal/propose) | Verb | Propose sends a Deal’s buyer a Quote they accept to place an Order. | | [Deal.win](/business/nouns/deal/win) | Verb | Win closes a Deal as won, which places its Order and makes the buyer a Customer. | | [Gathering.register](/business/nouns/gathering/register) | Verb | Register gives a Contact a place at a Gathering, or a waitlist place when the Gathering is full. | | [Lead.convert](/business/nouns/lead/convert) | Verb | Convert ends a qualified Lead’s pursuit as a Lead: it opens a Deal or routes the Lead to self-serve checkout. | | [Lead.qualify](/business/nouns/lead/qualify) | Verb | Qualify confirms a Lead matches an Offer’s ICP and opens a Deal for it. | | [Meeting.book](/business/nouns/meeting/book) | Verb | Book schedules a Meeting with a Contact at a time both calendars hold free. | | [Offer.grant](/business/nouns/offer/grant) | Verb | Grant adds an Entitlement to an Offer: a Verb its Customers may call, optionally bounded by a Limit. | | [Offer.subscribe](/business/nouns/offer/subscribe) | Verb | Subscribe accepts a recurring Offer as a Subscription that renews each period until it ends. | | [Offer.trial](/business/nouns/offer/trial) | Verb | Trial starts a Customer on an Offer free for a set number of days, with or without a card, converting or ending by its terms. | | [Offer.withdraw](/business/nouns/offer/withdraw) | Verb | Withdraw closes a published Offer to new Customers and leaves every existing Order and Subscription in force. | | [Order.cancel](/business/nouns/order/cancel) | Verb | Cancel ends an Order before fulfillment and returns any payment in full. | | [Order.place](/business/nouns/order/place) | Verb | Place commits a Customer to buy an Offer once and records the Offer Version and price at that moment. | | [PlayMix.compile](/business/nouns/play-mix/compile) | Verb | Compile builds the next Play Mix from the Demand Budget, each Play’s ledger and last week’s Acquisitions, and records the diff. | | [Prospect.engage](/business/nouns/prospect/engage) | Verb | Engage records a Prospect’s first reply or raised hand and makes it a Lead that keeps its Acquisition. | | [Quote.accept](/business/nouns/quote/accept) | Verb | Accept takes a sent Quote before it expires, turning one-time lines into an Order and recurring lines into a Subscription. | | [Quote.decline](/business/nouns/quote/decline) | Verb | Decline records the buyer’s refusal of a sent Quote, with the reason in their words. | | [Quote.expire](/business/nouns/quote/expire) | Verb | Expire closes a sent Quote that reached its validUntil date unaccepted; it never converts afterward. | | [Quote.request](/business/nouns/quote/request) | Verb | Request asks a Startup for terms on one or more Offers, with the volume, term or scope wanted. | | [Quote.send](/business/nouns/quote/send) | Verb | Send presents a drafted Quote to its buyer and freezes its lines, total and payment terms. | | [Quote.supersede](/business/nouns/quote/supersede) | Verb | Supersede replaces a sent Quote with a newer one on the same Deal; only the newest Quote can be accepted. | | [Waitlist.admit](/business/nouns/waitlist/admit) | Verb | Admit releases Leads from a Waitlist to the Offer they waited for, in the order the Waitlist ranks them. | | [Waitlist.join](/business/nouns/waitlist/join) | Verb | Join adds a Lead to a Waitlist for an Offer that is not open to them. | ## Next steps - [Demand](/systems/sales/demand): why demand is the constraint, and the Plays that find it. - [Reserve](/products/selling/reserve): deposits before the Product exists. - [Offers and pricing](/products/selling/offers-and-pricing): Products, Offers, Prices, and price tests. - [Earning models](/products/selling/earning-models): the five ways an Offer earns. - [Selling](/systems/sales/selling): self-serve acceptance, Deals, Quotes, and outbound. - [Selling to agents](/products/selling/selling-to-agents): quotes, the 402 reply, and Agent buyers. - [Customers](/products/selling/customers): the people ladder, and who pays when someone else acts. # ServiceBuilder URL: /code/builders/service · Id: `product:service-builder` > ServiceBuilder builds the service Products a Startup sells, delivered by Agents. ServiceBuilder turns a promised result into a [Service](/business/nouns/service) a [Startup](/business/nouns/startup) can sell, deliver, and get paid for. [Agents](/business/nouns/agent) do the work by default, and credentialed people join only where the promise or the law needs them. ## What it does ServiceBuilder reads the [Outcome Contract](/business/nouns/outcome-contract) on an [Offer](/business/nouns/offer) and builds everything the promise needs. Five terms in, a working delivery line out: - **Delivery.** Each step of the work is a [Verb](/business/nouns/verb) on the [Order](/business/nouns/order), run by code, a model, an Agent, or a [Human](/business/nouns/human). The [Customer](/business/nouns/customer) sees one status whoever runs it. - **Assurance.** [Evaluators](/business/nouns/evaluator) grade every delivery before the Customer sees it. Failed work goes back for another pass at no cost. - **Acceptance and earnings.** Delivery opens an acceptance window. The fee is held until the Customer confirms or the window closes, then it is earned. - **Remedy and disputes.** A miss runs the remedy the contract names. A contested result becomes a [Dispute](/business/nouns/dispute) with [Evidence](/business/nouns/evidence), a decision, and one appeal. - **Supply.** Where people do the work, ServiceBuilder recruits [Suppliers](/business/nouns/supplier), verifies their [Credentials](/business/nouns/credential), dispatches work, and pays them out. - **The legal floor.** Every [Reserved Act](/business/nouns/reserved-act) goes to a credentialed Human, whose [Attestation](/business/nouns/attestation) travels with the work. ## Built from - [Product](/business/nouns/product) - [Agent](/business/nouns/agent) - [api.sb](/code/platform/api-sb) ## Surfaces - The Customer's [Portal](/business/nouns/portal) on the Startup's [Site](/business/nouns/site): Orders, delivered work with its evidence, and the open acceptance window. - The supplier [App](/business/nouns/app): eligible work, Credentials on file, and earnings, on a phone. - startups.studio: the ServiceBuilder area holds every Order in delivery, the [Tasks](/business/nouns/task) waiting on people, open Disputes, and pending [Approvals](/business/nouns/approval). - [api.sb](/code/platform/api-sb): every delivery Verb under one name on every [Interface](/business/nouns/interface), so a buyer's Agent orders, tracks, and accepts work the way a person does. ```text API POST /{namespace}/orders/{order}/deliver SDK await $.Order.deliver({ order: 'order_1', work: {} }) CLI npx startup-builder do Order.deliver --json '{"order":"order_1","work":{}}' MCP do: return await $.Order.deliver({ order: 'order_1', work: {} }) ``` | Term | Kind | Definition | | --- | --- | --- | | [ServiceBuilder](/code/builders/service) | Product | ServiceBuilder builds the service Products a Startup sells, delivered by Agents. | | [startups.new](/start/startups-new) | Product | startups.new creates a Startup from one sentence and opens it in startups.studio. | | [Customer Team](/agents/customer) | Team | The Customer Team serves every Customer after the first acceptance: onboarding, support, retention, and the one Thread each Person has. | | [Finance Team](/agents/finance) | Team | The Finance Team moves and records the money: Invoices, dunning, refunds within a Limit, payouts, the monthly close, tax, and runway. | | [Legal Team](/agents/legal) | Team | The Legal Team keeps the Startup lawful: Agreements, privacy and Consent from day one, screening of every Offer, and every Reserved Act. | | [Operations Team](/agents/operations) | Team | The Operations Team runs the Startup day to day: it delivers outcomes, keeps human supply booked, stops abuse, and runs the Monday Role review. | | [People Team](/agents/people) | Team | The People Team staffs every Role: it names an Agent for each one, recruits the Humans the law or the Startup needs, and pays them. | | [Building](/business/lifecycle/states/building) | Lifecycle state | Building is the state of a Startup whose Agents build its Brand, Products, Offers, site, API, and MCP server from its template. | | [Live](/business/lifecycle/states/live) | Lifecycle state | Live is the state of a Startup that is publicly reachable and takes money from Customers for at least one Offer. | | [Repeatable](/business/lifecycle/states/repeatable) | Lifecycle state | Repeatable is the state of a Startup whose Customers arrive, pay, and stay, while its work runs without its founder. | | [Agent-run services firm](/start/templates/agent-run-services) | Startup Template | An Agent-run services firm runs with no humans and sells warranted outcomes as Services-as-Software, with the Agent behind them for hire. | | [Licensed professional network](/start/templates/licensed-network) | Startup Template | A Licensed professional network extends the Founder-led marketplace into a Licensed-human marketplace that buyers and their Agents book. | | [Managed service firm](/start/templates/managed-service-firm) | Startup Template | A Managed service firm extends the Agent-run services firm with Humans who share Roles and an E2E managed service for businesses. | | [E2E managed service](/products/templates/managed-service) | Product Template | An E2E managed service runs a whole business function for the Customer, with Agents doing the work and Humans in the loop. | | [Licensed-human marketplace](/products/templates/licensed-marketplace) | Product Template | A Licensed-human marketplace matches buyers with credentialed professionals and adds recruiting, Credential checks, and an App where they take work. | | [Marketplace](/products/templates/marketplace) | Product Template | A Marketplace matches buyers with Suppliers who deal with each other directly, and earns a take rate on every transaction it settles. | | [Services-as-Software](/products/templates/services-as-software) | Product Template | Services-as-Software sells a warranted outcome that Agents deliver end to end under an Outcome Contract, billed only once accepted. | | [Agreements](/systems/agreements) | System | Agreements drafts each Agreement between two or more Parties from Templates, routes it for signature, records who signed, and tracks its term and economics. | | [Compliance](/systems/compliance) | System | Compliance maps controls to frameworks, tests each from the records every Action leaves, and publishes the trust center buyers read. | | [Credentialing](/systems/credentialing) | System | Credentialing verifies each Supplier’s Credentials with the issuer, tracks expiry, and decides who may perform a Reserved Act. | | [Dispatch](/systems/dispatch) | System | Dispatch proposes each job to eligible, available Suppliers, books shifts, and proposes it again on decline before the deadline. | | [Earnings](/systems/payouts) | System | Earnings pays Suppliers, Partners and affiliates their earnings through Stripe, holds disputed amounts, and sends statements and year-end tax filings. | | [Evals](/agents/evals-system) | System | Evals grades outputs with versioned Evaluators, gates every Change before merge, and keeps each Worker’s track record. | | [Knowledge base](/systems/knowledge-base) | System | Knowledge base holds the articles Customers and Agents answer from, in a searchable help center that cites every answer. | | [Matchmaking](/systems/matching) | System | Matchmaking pairs buyers with Suppliers’ Offers, records the merchant of record on each Order, and takes the Startup’s fee through Stripe. | | [Phone](/systems/phone) | System | Phone holds a Startup’s numbers and runs voice calls and SMS, with voice Agents, transcripts and handoff to a Human. | | [Scheduling](/systems/scheduling) | System | Scheduling books Meetings between Workers and Contacts from shared availability and keeps the notes, Decisions and Tasks they produce. | | [Service delivery](/systems/service-delivery) | System | Service delivery runs each job to its Outcome Contract: steps, oversight per Verb, delivery, acceptance, remedy and proof. | | [Success](/systems/success) | System | Success moves each Customer to value and keeps them: onboarding checklists, health scores, renewals, saves and win-backs. | | [Supplier onboarding](/systems/supplier-onboarding) | System | Supplier onboarding recruits Suppliers: applications, identity and background checks, tax details, Agreements and a first assignment. | | [Support](/systems/support) | System | Support answers Conversations with Customers across email, chat and API, and links each reported bug or request to an Issue. | | [Trust and safety](/systems/trust-safety) | System | Trust and safety screens accounts, posts and Transactions for fraud and abuse, and acts on each report by stated rules. | | [Delivery](/workflows/processes/delivery) | Process | Delivery runs the Orders Customers place for Agent and Service outcomes, and bills only on confirmation. | | [Licensed review](/workflows/processes/licensed-review) | Process | Licensed review puts a credentialed Human’s Attestation on every Reserved Act before it reaches a Customer. | | [Onboarding](/workflows/processes/onboarding) | Process | Onboarding gets every new Customer to first value, by hand until the Startup automates each step. | | [Retention](/workflows/processes/retention) | Process | Retention keeps Customers by catching silence early, saving once, and winning back once. | | [Screening](/workflows/processes/screening) | Process | Screening tags the legal floor of every Offer and withdraws any Offer the Startup cannot lawfully deliver. | | [Supply](/workflows/processes/supply) | Process | Supply keeps enough credentialed Suppliers booked to meet demand and suspends any whose Credential lapses. | | [Support](/workflows/processes/support) | Process | Support answers every Conversation from the record in one Thread and fixes causes, not symptoms. | | [Bill on confirmation](/workflows/processes/delivery/bill-on-confirm) | Workflow | Bill on confirmation captures and bills each Service Order line the Customer confirms, as the Outcome Contract’s `earns` names. | | [Fan out an outcome](/workflows/processes/retention/fan-out-outcome) | Workflow | Fan out an outcome turns one confirmed Customer outcome into a dated number, and with Consent into a case study, quote and referral invite. | | [Start the remedy](/workflows/processes/delivery/start-remedy) | Workflow | Start the remedy holds the fee on a disputed Service Order and runs the Outcome Contract’s remedy: redo, refund, or credit. | | [Attestation](/business/nouns/attestation) | Noun | An Attestation is the signed, frozen act by which a credentialed Worker performs or declines a Reserved Act. | | [Builder](/business/nouns/builder) | Noun | A Builder is a named part of api.sb that builds one side of a Startup; StartupBuilder directs SiteBuilder, SoftwareBuilder, ServiceBuilder, and SalesBuilder. | | [Conversation](/business/nouns/conversation) | Noun | A Conversation is a Thread with one or more Contacts that a Worker must answer, such as a support request. | | [Credential](/business/nouns/credential) | Noun | A Credential is a standing authority a regulator grants a person or entity to perform certain acts in a jurisdiction. | | [Dispute](/business/nouns/dispute) | Noun | A Dispute is a contested payment or delivery, such as a chargeback, a rejected Service outcome, or a buyer’s claim against a Supplier. | | [Evaluator](/business/nouns/evaluator) | Noun | An Evaluator is a versioned Function that grades an output against a rubric and returns a verdict. | | [Human](/business/nouns/human) | Noun | A Human is a Worker who is a person, acting on Tasks through Apps, Mailboxes, and Channels. | | [Incident](/business/nouns/incident) | Noun | An Incident is an Issue where an Interface or Site fails Customers in production, tracked from detection to postmortem. | | [Issue](/business/nouns/issue) | Noun | An Issue is a Task reporting a problem or request, such as a bug or a feature request, with a reporter and a triage step. | | [Outcome Contract](/business/nouns/outcome-contract) | Noun | An Outcome Contract is the terms on an Offer that warrant a Service’s result: done, acceptance, assurance, remedy, and earnings. | | [Product Template](/business/nouns/product-template) | Noun | A Product Template is a reusable definition of one kind of Product: what it sells, who supplies the work, who buys, and how it earns. | | [Reserved Act](/business/nouns/reserved-act) | Noun | A Reserved Act is a Verb the law reserves to the holder of a named Credential, so its Function is always human. | | [Service](/business/nouns/service) | Noun | A Service is a Product that warrants an outcome, delivered by Agents and Humans under an Outcome Contract. | | [Source](/business/nouns/source) | Noun | A Source is something a Product draws on to keep its promise but did not build: owned, wrapped, or recruited. | | [Supplier](/business/nouns/supplier) | Noun | A Supplier is a Person or Company that delivers work through a Startup’s human supply: recruited, credentialed, and paid out. | | [Action.attest](/business/nouns/action/attest) | Verb | Attest records a credentialed Human’s signed performance of a Reserved Act that an Action needs to finish. | | [Credential.verify](/business/nouns/credential/verify) | Verb | Verify confirms a Credential with the authority that issued it and records when it expires. | | [Dispute.answer](/business/nouns/dispute/answer) | Verb | Answer submits the seller’s Evidence on an open Dispute before its deadline: the contract, the delivered work, and its verdicts. | | [Dispute.appeal](/business/nouns/dispute/appeal) | Verb | Appeal asks for one review of a decided Dispute by a Worker who took no part in the first decision. | | [Dispute.decide](/business/nouns/dispute/decide) | Verb | Decide rules on an answered Dispute for the buyer, the seller, or a split, and releases or returns the held amount. | | [Human.hold](/business/nouns/human/hold) | Verb | Hold sets aside part of a supplying Human’s earned balance against an open Dispute or an Order inside its clearance period. | | [Human.onboard](/business/nouns/human/onboard) | Verb | Onboard admits a recruited Human to supply work once their identity, Credentials and payout details verify. | | [Human.recruit](/business/nouns/human/recruit) | Verb | Recruit invites a person to supply credentialed work to a Startup through its supply App. | | [Human.release](/business/nouns/human/release) | Verb | Release frees a held amount for payout once its Dispute closes or its clearance period ends. | | [Human.remit](/business/nouns/human/remit) | Verb | Remit pays a supplying Human’s earned balance to their bank account through the Startup’s payment account. | | [Human.suspend](/business/nouns/human/suspend) | Verb | Suspend stops a supplying Human from taking new Tasks while a Credential lapses or a dispute is open. | | [Order.confirm](/business/nouns/order/confirm) | Verb | Confirm records the Customer’s sign-off on delivered work, which closes the Order and earns the Startup its fee. | | [Order.deliver](/business/nouns/order/deliver) | Verb | Deliver hands the finished work of a Service Order to its Customer and opens the acceptance window. | | [Order.dispute](/business/nouns/order/dispute) | Verb | Dispute contests a delivered Order under its Outcome Contract and starts the remedy the contract names. | | [Order.place](/business/nouns/order/place) | Verb | Place commits a Customer to buy an Offer once and records the Offer Version and price at that moment. | | [Order.revise](/business/nouns/order/revise) | Verb | Revise sends delivered lines back for one counted revision, with the changes the Customer asks for. | | [Order.start](/business/nouns/order/start) | Verb | Start checks a Service Order’s inputs against its brief, then moves it from intake to working and starts its deadline. | | [Quote.decline](/business/nouns/quote/decline) | Verb | Decline records the buyer’s refusal of a sent Quote, with the reason in their words. | | [Quote.request](/business/nouns/quote/request) | Verb | Request asks a Startup for terms on one or more Offers, with the volume, term or scope wanted. | | [Quote.send](/business/nouns/quote/send) | Verb | Send presents a drafted Quote to its buyer and freezes its lines, total and payment terms. | | [Quote.supersede](/business/nouns/quote/supersede) | Verb | Supersede replaces a sent Quote with a newer one on the same Deal; only the newest Quote can be accepted. | ## Next steps - [Services](/products/service/services): what a Service sells, and how it differs from [Software](/business/nouns/software) and a [Marketplace](/products/templates/marketplace). - [Outcome contracts](/products/service/outcome-contracts): the five terms every Service keeps. - [Delivery and acceptance](/products/service/delivery-and-acceptance): an Order from placed to earned. - [Services-as-Software](/products/templates/services-as-software): start from the [Product Template](/business/nouns/product-template). # Design system URL: /code/builders/site/design-system · Id: `page:code/builders/site/design-system` > Design is data, so a Page is a Template placing Components styled by a Theme, and no Agent writes markup or CSS on the default path. Design is data: a [Page](/business/nouns/page) is a [Template](/business/nouns/template) placing [Components](/business/nouns/component), styled by a [Theme](/business/nouns/theme). No [Agent](/business/nouns/agent) writes markup or CSS on the default path, so every [Site](/business/nouns/site) stays consistent, accessible, and inside one performance budget. ## Why design is data An Agent asked to write HTML writes it differently each time, and every variation is a new place for a bug. A thousand Sites built that way are a thousand codebases to fix. So the design system holds the markup once. An Agent chooses Components and fills their props from records, and the renderer turns that choice into HTML. A fix to one Component reaches every Page that places it on the next request. ## Components A Component is a named, typed block: a hero, a pricing table, a questions list, a [Form](/business/nouns/form). Its props have a schema, so a Page that passes the wrong data fails a check instead of rendering a broken block. Components nest in a fixed order. Regions frame the Page, such as the header, the footer, and notices, and sections between them hold items and cards. Every interactive Component renders a static still first, so the Page works without JavaScript and an Agent reads what a person sees. ## Templates A Template is reusable [Content](/business/nouns/content) with variables, filled from the graph. It places Components by name and sets the page frame with a `shell` value, never with class names. Here is the listing Template of a [Directory](/products/templates/directory) of solar installers: ```mdx --- shell: marketing --- ``` One Template renders three thousand installer Pages. Templates also fill a renewal [Message](/business/nouns/message) and a quote [Document](/business/nouns/document), and one edit updates everything built from a Template. Templates are versioned and take the Theme of the [Brand](/business/nouns/brand) they render under. ## Themes A Theme is the design tokens of a Brand: color, type, spacing, radius, and motion, in light and dark modes. Components read the tokens as CSS variables at the root of the Page, so swapping the Theme restyles every Page without editing one. ```json { "color": { "light": { "accent": "oklch(55% 0.15 45)", "ink": "oklch(22% 0.01 60)", "paper": "oklch(98% 0.005 80)" }, "dark": { "accent": "oklch(72% 0.14 45)", "ink": "oklch(94% 0.01 80)", "paper": "oklch(20% 0.01 60)" } }, "font": { "display": "Fraunces", "body": "Source Sans 3" }, "radius": { "card": "10px" }, "motion": { "duration": "160ms", "reduce": "0ms" } } ``` A [Studio](/business/nouns/studio) sets the floor every Theme inherits: the type scale ratio, contrast minimums, a motion ceiling, and radius bounds. Each Brand derives its own palette, type pair, and logo on that floor, and may only tighten it. A Brand that extends another inherits its tokens and overrides only its own accent and logo, as [Brand](/business/brand) describes. Siblings whose [ICPs](/business/nouns/icp) overlap never share a face. Their accent hues sit at least 30 degrees apart in `oklch`, and they differ in display typeface and in logo form. A Theme [Change](/business/nouns/change) that brings a [Startup](/business/nouns/startup) inside a sibling's distance fails its [Guard](/business/nouns/guard), and the failure names the sibling. ## Override in the lowest layer When a Page needs to look different, the change goes in the lowest layer that achieves it. Each layer overrides the ones above it, and nothing is forked. | Layer | What it changes | Example | | --- | --- | --- | | Content | The words and media | A new headline | | Props | One Component on one Page | A pricing table showing annual prices | | Template | Which Components a Page places, in what order | A comparison section above pricing | | Theme tokens | Every Component on the Site | A new accent color | | CSS | Styling the tokens do not reach | A custom hero background | | Component replacement | The Component itself | An interactive savings calculator | A Template declares where it widens a Component's bounds, up to that Component's ceiling, and a Theme may only tighten them. A Site that replaces one Component still receives every fix to the others. The replacement runs as the [Startup](/business/nouns/startup)'s own code, isolated from every other Startup. ## One design, three renderers The same Page data renders three ways: screens for [Humans](/business/nouns/human), Markdown for Agents, and JSON for native clients. A Component declares all three, so a pricing table becomes a Markdown table for an Agent and a list of [Offers](/business/nouns/offer) in JSON. Hand-written markup cannot do this. A renderer turns a typed `Pricing` block into Markdown, but it cannot recover the meaning of an arbitrary `div`. Every [Dashboard](/business/nouns/dashboard) renders through the same three renderers for the same reason. ## The quality gate The [Designer](/agents/product/designer) reviews every new Component and Theme before any Site can use it. A new Component is a code release and passes the same checks as the platform. Before a [Version](/business/nouns/version) deploys, every changed Page renders at phone, tablet, and desktop widths in three browser engines, with accessibility checks on each render. On narrow screens, primary calls to action span the full width and stack above secondary ones. An [Evaluator](/business/nouns/evaluator) then grades each changed render from 1 to 5 against the visual rubric: | Rule | Passes when | | --- | --- | | One action | Each viewport holds one primary call to action | | Scale | Type levels step by a ratio of 1.2 or more | | Measure | Body lines run 45 to 75 characters | | Restraint | At most two typefaces and one accent | | Rhythm | Spacing sits on a 4px grid | | Imagery | Pictures come from the buyer's world, as [Brand](/business/brand#imagery) requires | A render below 4 opens a Change for the Designer. The Evaluator never runs the Designer's model, and every release checks it against a set of known-bad renders. Every public Page also meets its performance budget at p75 on a mid-range phone over 4G. The largest element paints within 1.5 seconds, layout shift stays under 0.05, and input responds within 150 milliseconds. HTML and CSS weigh at most 60 KB compressed, and reading or buying needs no JavaScript. A Theme loads at most two font families, subset to the Brand's languages, with metric-matched fallbacks so text never shifts. A Change that breaks the budget fails and names the Page and the metric. ## Next - [Brand](/business/brand): the identity a Theme expresses. - [Publishing](/products/site/publishing): how a design change reaches readers. # SiteBuilder URL: /code/builders/site · Id: `product:site-builder` > SiteBuilder builds and serves the site of a Startup under its Brand. SiteBuilder builds and serves the [Site](/business/nouns/site) of a [Startup](/business/nouns/startup): its [Brand](/business/nouns/brand), [Pages](/business/nouns/page), [Domains](/business/nouns/domain), and customer [Portal](/business/nouns/portal). Every Page is one record, served as HTML to people, Markdown to [Agents](/business/nouns/agent), and JSON to software. ## What it does **Compiled from** the founding [Hypothesis](/business/nouns/hypothesis) of the Startup, its [Products](/business/nouns/product), and its [Offers](/business/nouns/offer). Every claim on a Page names the record and version it came from, so a pivot rewrites the Site as a reviewable diff. Each [Lifecycle](/business/nouns/lifecycle) state asks the Site for something different: - **[Idea](/business/nouns/idea).** One Page and a [Waitlist](/business/nouns/waitlist) test demand before the Product exists. The Page indexes at once, because it promises nothing a buyer can pay for. - **[Building](/business/lifecycle/states/building).** The Brand and its [Theme](/business/nouns/theme), the standard Pages, and a free subdomain. Selling Pages stay out of search. - **[Live](/business/lifecycle/states/live).** The canonical Domain over HTTPS, checkout, the Portal, and the machine registers: `llms.txt`, `agents.json`, and OpenAPI. - **[Repeatable](/business/lifecycle/states/repeatable) and [Scale](/business/lifecycle/states/scale).** Comparison and answer Pages released to search in batches, and Page [Experiments](/business/nouns/experiment) judged by a [Metric](/business/nouns/metric). Three Live entry checks belong to SiteBuilder: the Site is published, the Portal is ready, and the address resolves. No Agent writes markup or CSS. A Page is a [Template](/business/nouns/template) placing [Components](/business/nouns/component), so every edit is data. ## Built from - [Brand](/business/nouns/brand) - [Startup](/business/nouns/startup) - [api.sb](/code/platform/api-sb) ## Surfaces Owners edit a Site in [startups.new](/start/startups-new) by pointing at the part to change, and preview it as a [Visitor](/business/nouns/visitor), a [Customer](/business/nouns/customer), or an Agent. Each edit card names the [layer](/code/builders/site/design-system#override-in-the-lowest-layer) the edit landed in: `Hero headline → Books closed by day 5, every month · Content`. Every operation reads the same through each [Interface](/business/nouns/interface). Here an Agent adds a pricing Page to `chairbooks.com`, a bookkeeping [Service](/business/nouns/service) for dental practices: **Ask** ```text Add a pricing page. ``` **API** ```bash curl -X POST https://api.sb/chairbooks.com/pages \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"path":"/pricing","kind":"pricing"}' ``` **SDK** ```ts import { $ } from 'startup-builder' const page = await $.Page.create({ path: '/pricing', kind: 'pricing' }) ``` **CLI** ```bash npx startup-builder do Page.create --json '{"path":"/pricing","kind":"pricing"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Page.create({ path: '/pricing', kind: 'pricing' })" } } ``` | Term | Kind | Definition | | --- | --- | --- | | [SiteBuilder](/code/builders/site) | Product | SiteBuilder builds and serves the site of a Startup under its Brand. | | [startups.new](/start/startups-new) | Product | startups.new creates a Startup from one sentence and opens it in startups.studio. | | [Engineering Team](/agents/engineering) | Team | The Engineering Team builds and runs every Product: it implements Nouns and Verbs, ships Changes behind replay, and keeps every Interface up. | | [Marketing Team](/agents/marketing) | Team | The Marketing Team creates and harvests demand: the Brand story, launches, Content, Experiments, and the Metrics the whole Startup reads. | | [Product Team](/agents/product) | Team | The Product Team decides what gets built and why: Product definitions, list Prices and packaging, the build list, and the Site’s Pages for each ICP. | | [Building](/business/lifecycle/states/building) | Lifecycle state | Building is the state of a Startup whose Agents build its Brand, Products, Offers, site, API, and MCP server from its template. | | [Live](/business/lifecycle/states/live) | Lifecycle state | Live is the state of a Startup that is publicly reachable and takes money from Customers for at least one Offer. | | [Autonomous directory](/start/templates/autonomous-directory) | Startup Template | An Autonomous directory runs with no humans and sells listings in a Directory to Organizations that want buyers and Agents to find them. | | [Autonomous storefront](/start/templates/autonomous-storefront) | Startup Template | An Autonomous storefront runs with no humans and sells physical goods as a Dropship store to people and the Agents that shop for them. | | [Solo SaaS](/start/templates/solo-saas) | Startup Template | A Solo SaaS has one Human founder and Agents in every other Role, selling SaaS and its Headless SaaS to businesses and people. | | [Directory](/products/templates/directory) | Product Template | A Directory sells listings: Organizations pay to appear in a searchable Dataset that buyers and their Agents browse free. | | [Dropship store](/products/templates/dropship-store) | Product Template | A Dropship store sells physical goods from a catalog while an upstream holds the stock and ships each Order, with tracking passed through. | | [SaaS](/products/templates/saas) | Product Template | SaaS adds an App for people to Headless SaaS, sold as a Subscription per seat, with onboarding to first value. | | [Changelog](/code/systems/changelog) | System | Changelog publishes what shipped in each Version as dated notes on the Site, in feeds and to subscribed Customers. | | [CMS](/systems/cms) | System | CMS holds authored Content, from posts to docs to legal Pages, with drafts, schedules and revisions, rendered on every Interface. | | [Forms](/systems/forms) | System | Forms collects structured answers on a Site or in a Message and routes each submission to a Lead, Evidence or another Thing. | | [Knowledge base](/systems/knowledge-base) | System | Knowledge base holds the articles Customers and Agents answer from, in a searchable help center that cites every answer. | | [Listings](/systems/listings) | System | Listings presents other Parties in a public Collection: unclaimed profiles, claims, verification, paid placement and moderation. | | [Media production](/systems/media) | System | Media production makes a Startup’s Videos, images and voice from its records: drafted, generated, rendered per format, checked, then finalized for publishing. | | [Privacy](/systems/privacy) | System | Privacy declares each Purpose for personal data, records Consent, answers access requests, masks data on request, and publishes its privacy notices. | | [Product analytics](/systems/product-analytics) | System | Product analytics turns the Visits and Events captured on every Domain and API into the conversion, activation and retention Metrics every Team reads. | | [SEO](/systems/seo) | System | SEO tracks the Keywords and AI prompts a Startup’s Pages target, where they rank, which links point at them, and which answers cite them. | | [Sites](/products/site/sites) | System | Sites keeps each Site with its Pages, navigation and Brand, served on one or more Domains, with previews, redirects and rollbacks. | | [Waitlists](/systems/waitlists) | System | Waitlists holds the Leads waiting for an Offer that is not open to them and invites them ranked as a Setting chooses. | | [Content marketing](/workflows/processes/content-marketing) | Process | Content marketing publishes the Pages, answers, and data reports that bring buyers and Agents to a Startup. | | [Experimentation](/workflows/processes/experimentation) | Process | Experimentation tests one change against a control, with the threshold fixed before the start. | | [Launches](/workflows/processes/launches) | Process | Launches tell the right Audiences a Startup is live, where those Audiences already look. | | [Release](/workflows/processes/release) | Process | Release takes each reviewed Change to all traffic in stages, with automatic revert. | | [Shipping](/workflows/processes/shipping) | Process | Shipping delivers the most valuable Change every day and prunes what nobody uses every week. | | [Compile the demand kit](/workflows/processes/launches/compile-demand-kit) | Workflow | Compile the demand kit emits every asset the demand Plays read before the first one runs, each tagged with its lineage. | | [Design first run](/workflows/processes/product-definition/design-first-run) | Workflow | Design first run compiles sample records, empty states and the shortest path to an Offer’s activation event from the definition. | | [Acquisition](/business/nouns/acquisition) | Noun | An Acquisition is how a Visitor or Prospect first arrived, recorded on its first Event: the referrer kind, the Play, the campaign, and the medium. | | [Builder](/business/nouns/builder) | Noun | A Builder is a named part of api.sb that builds one side of a Startup; StartupBuilder directs SiteBuilder, SoftwareBuilder, ServiceBuilder, and SalesBuilder. | | [Component](/business/nouns/component) | Noun | A Component is a named block of a Page, such as a hero, a pricing table, or a form, filled from records through typed props. | | [Content](/business/nouns/content) | Noun | Content is authored material with a draft and a published state, such as a post, an article, or a changelog entry. | | [DNS Record](/business/nouns/dns-record) | Noun | A DNS Record is one DNS answer of a Domain: its type, name and value, who owns it, and what the world last answered. | | [Domain](/business/nouns/domain) | Noun | A Domain is a hostname that points at a Thing, with a role, a status, and a lifecycle tracked as data. | | [Form](/business/nouns/form) | Noun | A Form is a set of fields someone fills in on a Site or in a Message, producing a Lead, Evidence, or a Thing. | | [Funnel](/business/nouns/funnel) | Noun | A Funnel is a designed path to an Offer: a landing Page, an opt-in that makes a Lead, a Sequence, then the Offer. | | [Keyword](/business/nouns/keyword) | Noun | A Keyword is a search phrase or AI prompt that Pages target, with its rank and citations observed over time. | | [Page](/business/nouns/page) | Noun | A Page is an addressable page of a Site, of a named type such as pricing, about one Thing or each member of a Collection. | | [Portal](/business/nouns/portal) | Noun | A Portal is the signed-in part of a Site where each Customer orders, tracks delivery, accepts work, and pays, seeing only their own records. | | [Publication](/business/nouns/publication) | Noun | A Publication is the branded package a Startup’s Customers use: Domain, Interfaces, packages, docs and Portal, compiled from its Brand and a Version. | | [Site](/business/nouns/site) | Noun | A Site is a website as a Thing: its Pages, navigation, and Brand, served on one or more Domains. | | [Story](/business/nouns/story) | Noun | A Story is the customer narrative for one ICP, compiled from its Founding Hypothesis and Interview quotes, never written by hand. | | [Template](/business/nouns/template) | Noun | A Template is reusable Content with variables, filled from Things in the graph and authored as MDX, rendering a Message, Document, or Page. | | [Theme](/business/nouns/theme) | Noun | A Theme is the design tokens of a Brand, its color, type, spacing, radius, and motion, that every Component reads when it renders. | | [Video](/business/nouns/video) | Noun | A Video is a timed composition held as data: a timeline of scenes and spoken lines, drafted from records and rendered per format. | | [Visit](/business/nouns/visit) | Noun | A Visit is one span of a Visitor’s Events on a Startup’s Sites and Apps. | | [Visitor](/business/nouns/visitor) | Noun | A Visitor is someone a Startup cannot name, known by an id scoped to that Startup. | | [DNSRecord.remove](/business/nouns/dns-record/remove) | Verb | Remove stops a Startup-owned DNS Record from answering; its history stays and a revert restores it. | | [DNSRecord.set](/business/nouns/dns-record/set) | Verb | Set adds or changes a Startup-owned DNS Record through a Change, previewed against what the Domain answers today. | | [Document.render](/business/nouns/document/render) | Verb | Render produces a file from a Document in the format the reader asks for. | | [Domain.claim](/business/nouns/domain/claim) | Verb | Claim gives a Startup a one-label name under an issuing Domain, or assigns it a held Domain through an approved Change. | | [Domain.connect](/business/nouns/domain/connect) | Verb | Connect attaches a hostname a Startup already holds and verifies ownership through DNS. | | [Domain.register](/business/nouns/domain/register) | Verb | Register buys a hostname for a Startup and points it at the Startup’s address. | | [Domain.release](/business/nouns/domain/release) | Verb | Release lets a Domain’s registration or claim end, keeping its record, history and aliases. | | [Domain.renew](/business/nouns/domain/renew) | Verb | Renew extends a Domain’s registration by whole years at its renewal price, paid by its owner of record. | | [Domain.search](/business/nouns/domain/search) | Verb | Search lists candidate names with availability, first-year price, renewal price and the rules of each extension. | | [Domain.transfer](/business/nouns/domain/transfer) | Verb | Transfer moves a Domain’s registration to another holder or registrar, with its records intact. | | [Domain.verify](/business/nouns/domain/verify) | Verb | Verify checks a Domain’s DNS, ownership and certificate again and records each result, with the fix for any failure. | | [Problem.suggest](/business/nouns/problem/suggest) | Verb | Suggest records a Customer’s ask for something the Product lacks as Evidence on a Problem, with the asker attached. | | [Site.publish](/business/nouns/site/publish) | Verb | Publish puts a Site’s current Pages live on its Domains, under its Brand. | | [Version.deploy](/business/nouns/version/deploy) | Verb | Deploy points a Startup’s live address at a Version, so every Interface serves that build. | | [Waitlist.join](/business/nouns/waitlist/join) | Verb | Join adds a Lead to a Waitlist for an Offer that is not open to them. | ## Next steps - [Sites and Pages](/products/site/sites-and-pages): what a Site holds and how its Pages compile from the definition. - [Design system](/code/builders/site/design-system): Components, Themes, Templates, and the override layers. - [Brand](/business/brand): the name, voice, logo, and style every surface renders from. - [Domains](/products/site/domains/site-domains): how a Startup gets an address and keeps it. - [Publishing](/products/site/publishing): one record served as HTML, Markdown, and JSON. - [Indexing](/systems/marketing/indexing): which Pages search engines see, and when. - [Storefront and Portal](/products/site/storefront-and-portal): where Customers buy and receive. # Compatibility URL: /code/builders/software/compatibility · Id: `page:code/builders/software/compatibility` > A Live Startup's API is a contract: every Change is classified, breaking Changes bump the version, and every pinned version keeps serving. A [Live](/business/lifecycle/states/live) [Startup](/business/nouns/startup)'s API is a contract with every [Customer](/business/nouns/customer) whose code calls it. A gate classifies each [Change](/business/nouns/change) against the published [Interfaces](/business/nouns/interface), so no merge breaks a caller. ## Additive or breaking Every Change to a Live Startup's [Nouns](/business/nouns/noun) and [Verbs](/business/nouns/verb) is classified at review, from its diff. | Change | Kind | | --- | --- | | A new Noun, Verb, [Event](/business/nouns/event), or optional input | Additive | | A new property on an output | Additive | | A removed or renamed Noun, Verb, property, or Event | Breaking | | A new required input, or a narrower type or enum | Breaking | | A changed meaning, unit, or default [Mode](/business/nouns/mode) | Breaking | | A stricter rule on an existing Verb | Breaking | An additive Change ships to every version at once. A restyle, a copy edit, or a new [Page](/business/nouns/page) is not an API Change at all, and never touches the version. ## Breaking Changes bump the version A breaking Change merges only as a new API version, `v2` after `v1`, with a version gate: a pair of transforms between the two shapes. Requests at `v1` pass through the gate down, and responses come back up, so `v1` callers see exactly what they saw before. [SoftwareBuilder](/code/builders/software) writes the gate when the diff is mechanical: a rename, a split field, a new required input with a default. A change of meaning needs a gate written by hand. A breaking Change with no gate is `refused` with reason `breaking_change_unversioned`, and the merge waits. ## Every caller pins a version A caller always knows which contract it gets. | Caller | What pins its version | | --- | --- | | An API key | The version current when the key was created | | A request | A version in its path, such as `/v1`, overriding the key | | The SDK | Its major release | | A webhook endpoint | The version current when it subscribed, for every Event it receives | | An [Agent](/business/nouns/agent) over MCP | Its key: tool names and descriptions match that version's reference | An unversioned path tracks the latest version. Pinned versions keep serving for as long as any caller pins them; nothing retires a version a Customer still calls. ## Upgrading A Customer upgrades on its own schedule. It points a `test` key at the new version, runs its own code against it, then moves its `live` key's pin. Each version's reference shows the shapes that version serves, and every page marks what changed since the one before. The [Changelog](/code/systems/changelog) [System](/business/nouns/system) publishes every version the moment it merges. Notes come from the gates: what changed, which Verbs it touches, and the one-line upgrade. Customers subscribe by email, feed, or webhook, and an Agent reads the same notes in Markdown. ## A worked upgrade ratebook.dev sells sales-tax rates to online checkouts. Its `Rate.lookup` Verb returned one `rate` and one `jurisdiction`. Customers asked for the county share, so the Startup renamed `rate` to `percent` and split `jurisdiction` into `state` and `county`. SoftwareBuilder classified the Change as breaking and derived the gate from the diff. The merge shipped `v2`, and every existing key stayed on `v1`: ```bash # Pinned by the key: the v1 shape, unchanged curl "https://api.sb/ratebook.dev/rates/lookup?zip=94107" \ -H "Authorization: Bearer $RATEBOOK_KEY" # { "rate": 8.625, "jurisdiction": "San Francisco, CA" } # Pinned by the path: the v2 shape curl "https://api.sb/ratebook.dev/v2/rates/lookup?zip=94107" \ -H "Authorization: Bearer $RATEBOOK_KEY" # { "percent": 8.625, "state": "CA", "county": "San Francisco" } ``` ## Next [SoftwareBuilder](/code/builders/software) lists what builds each part, and the [API routes](/code/api/reference) lists every route. # Implementation URL: /code/builders/software/implementation · Id: `page:code/builders/software/implementation` > Each Interface, System, or Verb runs managed, custom, or external, and the Customer's contract stays the same whichever kind runs it. An [Implementation](/business/nouns/implementation) is how an [Interface](/business/nouns/interface), [System](/business/nouns/system), or [Verb](/business/nouns/verb) of a [Product](/business/nouns/product) runs: managed, custom, or external. The kind can change at any time, and the [Customer](/business/nouns/customer)'s contract never changes with it. ## Three kinds | Kind | What runs | Who maintains it | | --- | --- | --- | | Managed | Code [SoftwareBuilder](/code/builders/software) compiles from the definition | The platform | | Custom | The [Startup](/business/nouns/startup)'s own code, running on the platform | The Startup | | External | A server elsewhere, with [api.sb](/code/platform/api-sb) routing each call to it | The Startup or a [Source](/business/nouns/source) | Managed is the default. Every inherited `create`, `get`, `list`, `update`, and `delete`, every declared rule, and every generated Interface runs managed until the Startup says otherwise. ## Mixed per Verb One Product mixes kinds freely. episodely.fm sells podcast production to independent shows, and its Product runs managed. Its `Episode.transcribe` Verb runs custom code tuned for crosstalk, and `Episode.syndicate` runs external, on a feed server the Startup keeps elsewhere. A System can run external too. The Startup keeps the System's [Nouns](/business/nouns/noun) and Verbs and routes them through an [Integration](/business/nouns/integration). It still owns the records, and the outside product is a Source. ## The Function behind the Verb A [Function](/business/nouns/function) carries each Verb's execution: code, a generative model, an [Agent](/business/nouns/agent), or a [Human](/business/nouns/human). The caller never sees which. Every call returns the same [Action](/business/nouns/action), with the same statuses and the same [Events](/business/nouns/event). That makes a swap free. episodely.fm's show notes start with a human editor; an Agent then runs the same Verb in shadow, its output graded and never shipped. When an [Evaluator](/business/nouns/evaluator) agrees with the Agent on 95% of a sample, the Agent takes the Verb, and no caller changes a line. ## What stays fixed The Product's identity never moves with its code. Its [Domains](/business/nouns/domain), [Brand](/business/nouns/brand), Customers, [Tenants](/business/nouns/tenant), [Entitlements](/business/nouns/entitlement), billing, and history stay in place whichever kind runs. Every call still becomes an Action on api.sb. Moving a Product to external is ejecting, and it changes no address. An ejected Startup keeps its Customers, its revenue, and its books. ## Changes, Versions, and deploys Some edits are data: copy, an [Offer](/business/nouns/offer), a price, a [Dataset](/business/nouns/dataset) fact. Others are behavior: a new Verb or new custom code. Both arrive as a [Change](/business/nouns/change), previewed on its own branch, checked, and merged as one unit. Each merge produces a new [Version](/business/nouns/version), an immutable build at a fingerprint. [Deploy](/business/nouns/version/deploy) points the Startup's live address at that Version, and every Interface serves it at once. [Revert](/business/nouns/change/revert) undoes a merged Change with a new one. A Change to a Live Startup's Nouns or Verbs also faces the [compatibility](/code/builders/software/compatibility) gate. A restyle or a copy edit never does. ## Deploy and publish A deploy serves code; [publish](/business/nouns/offer/publish) makes an Offer available to accept. A Product is available only when both hold: its Version is live, and an Offer for it is published. Publishing carries what the Customer relies on, not only code. A Dataset publishes its coverage and terms, and [Software](/business/nouns/software) publishes its Verbs and how Tenants stay apart. An Agent Product publishes the task types it accepts and its eval results. ## Next [Compatibility](/code/builders/software/compatibility) covers how a Live Startup changes its API without breaking its Customers. # SoftwareBuilder URL: /code/builders/software · Id: `product:software-builder` > SoftwareBuilder builds the software Products a Startup sells: APIs, apps, SDKs, and MCP servers. SoftwareBuilder builds the digital [Products](/business/nouns/product) a [Startup](/business/nouns/startup) sells: [Software](/business/nouns/software), [Datasets](/business/nouns/dataset), and [Agents](/business/nouns/agent). It compiles each Product's [Nouns](/business/nouns/noun) and [Verbs](/business/nouns/verb) into every [Interface](/business/nouns/interface), so one definition runs everywhere. ## What it does From one definition, SoftwareBuilder compiles each Verb's API route, SDK method, CLI command, MCP call, [App](/business/nouns/app) screen, webhook [Event](/business/nouns/event), and reference row. Each Verb keeps one name, such as `Swap.approve`, so no two Interfaces disagree. - **Software** keeps each [Customer](/business/nouns/customer)'s records in its own [Tenant](/business/nouns/tenant) and enforces every rule its Verbs declare. See [Software](/products/app/software). - **Datasets** read each [Source](/business/nouns/source) on schedule and serve lookup, search, and bulk access, every value with its origin. See [Datasets](/products/data/datasets). - **Agents** pair a [Role](/business/nouns/role) with an eval suite; [mint](/business/nouns/agent/mint) gives each Customer its own, billed on graded work. See [Agents](/products/agent/agents). - A composite Product computes its coverage, cost, and remedy from its parts: see [composition](/products/composition). - Every [Change](/business/nouns/change) to a Live API is classified, and every pinned version keeps serving: see [compatibility](/code/builders/software/compatibility). Every call checks [Entitlements](/business/nouns/entitlement), counts usage on a [Meter](/business/nouns/meter), and returns an [Action](/business/nouns/action). Code runs managed by default; any Verb can switch to a custom or external [Implementation](/business/nouns/implementation). ## Built from - [Product](/business/nouns/product) - [Noun](/business/nouns/noun) - [Verb](/business/nouns/verb) - [api.sb](/code/platform/api-sb) ## Surfaces - [api.sb](/code/platform/api-sb) serves each Product's Nouns as collections under the Startup's namespace, with OpenAPI, `llms.txt`, and `agents.json`. - The `startup-builder` package holds the typed [SDK](/code/sdk/reference) and the [CLI](/code/cli/reference). - The api.sb [MCP server](/code/mcp/reference) runs any Verb for an Agent, within its Role. - Each record's address answers in HTML, JSON, and Markdown. | Term | Kind | Definition | | --- | --- | --- | | [SoftwareBuilder](/code/builders/software) | Product | SoftwareBuilder builds the software Products a Startup sells: APIs, apps, SDKs, and MCP servers. | | [startups.new](/start/startups-new) | Product | startups.new creates a Startup from one sentence and opens it in startups.studio. | | [Engineering Team](/agents/engineering) | Team | The Engineering Team builds and runs every Product: it implements Nouns and Verbs, ships Changes behind replay, and keeps every Interface up. | | [Product Team](/agents/product) | Team | The Product Team decides what gets built and why: Product definitions, list Prices and packaging, the build list, and the Site’s Pages for each ICP. | | [Quality Team](/agents/quality) | Team | The Quality Team checks all work: the checks inside each Process, every outbound Message, and every money move, with verdicts, never Approvals. | | [Building](/business/lifecycle/states/building) | Lifecycle state | Building is the state of a Startup whose Agents build its Brand, Products, Offers, site, API, and MCP server from its template. | | [Live](/business/lifecycle/states/live) | Lifecycle state | Live is the state of a Startup that is publicly reachable and takes money from Customers for at least one Offer. | | [Repeatable](/business/lifecycle/states/repeatable) | Lifecycle state | Repeatable is the state of a Startup whose Customers arrive, pay, and stay, while its work runs without its founder. | | [Declared Verb attempts](/agents/product#declared-verb-attempts) | Metric | Declared Verb attempts counts live calls in 7 days to each Verb no Function runs yet, ranking which Function to build next. | | [Autonomous agent business](/start/templates/autonomous-agent) | Startup Template | An Autonomous agent business runs with no humans and sells Agent as a Service to businesses, people, and other Agents. | | [Autonomous data API](/start/templates/autonomous-data-api) | Startup Template | An Autonomous data API runs with no humans and sells a Dataset API and Headless SaaS to developers and their Agents. | | [Solo SaaS](/start/templates/solo-saas) | Startup Template | A Solo SaaS has one Human founder and Agents in every other Role, selling SaaS and its Headless SaaS to businesses and people. | | [Agent as a Service](/products/templates/agent-as-a-service) | Product Template | Agent as a Service sells an Agent that Customers hire into a Role or hand Tasks to through the API or MCP server. | | [Dataset API](/products/templates/dataset-api) | Product Template | A Dataset API sells keyed lookups and queries over a Dataset to developers and Agents, metered per call. | | [Directory](/products/templates/directory) | Product Template | A Directory sells listings: Organizations pay to appear in a searchable Dataset that buyers and their Agents browse free. | | [Dropship store](/products/templates/dropship-store) | Product Template | A Dropship store sells physical goods from a catalog while an upstream holds the stock and ships each Order, with tracking passed through. | | [Headless SaaS](/products/templates/headless-saas) | Product Template | Headless SaaS sells Software with no App of its own: Customers and their Agents use it through the API, MCP server, SDK, and CLI. | | [Licensed-human marketplace](/products/templates/licensed-marketplace) | Product Template | A Licensed-human marketplace matches buyers with credentialed professionals and adds recruiting, Credential checks, and an App where they take work. | | [Marketplace](/products/templates/marketplace) | Product Template | A Marketplace matches buyers with Suppliers who deal with each other directly, and earns a take rate on every transaction it settles. | | [SaaS](/products/templates/saas) | Product Template | SaaS adds an App for people to Headless SaaS, sold as a Subscription per seat, with onboarding to first value. | | [Changelog](/code/systems/changelog) | System | Changelog publishes what shipped in each Version as dated notes on the Site, in feeds and to subscribed Customers. | | [Compliance](/systems/compliance) | System | Compliance maps controls to frameworks, tests each from the records every Action leaves, and publishes the trust center buyers read. | | [Customer access](/systems/customer-access) | System | Customer access governs who acts in each Customer’s Tenant: members, invitations, Roles, Permissions, sign-in connections, directory sync and keys. | | [Data editor](/code/systems/data-editor) | System | Data editor edits a Startup’s own Nouns directly: tables, saved views, imports, exports and bulk Changes. | | [Datasets](/systems/datasets) | System | Datasets is the System behind each Dataset: curated Things of one Noun, built from Sources plus enrichment, refreshed and checked against its promise. | | [Evals](/agents/evals-system) | System | Evals grades outputs with versioned Evaluators, gates every Change before merge, and keeps each Worker’s track record. | | [Flags](/systems/flags) | System | Flags decides which copy or behavior each Visitor, Customer or request gets, by rules and sticky splits evaluated at the edge. | | [Listings](/systems/listings) | System | Listings presents other Parties in a public Collection: unclaimed profiles, claims, verification, paid placement and moderation. | | [Monitoring](/code/systems/monitoring) | System | Monitoring captures errors, logs and traces, checks uptime and scheduled jobs, and ties each failure to the Version that caused it. | | [Product planning](/code/systems/product-planning) | System | Product planning groups feature-request Issues toward Goals, ranks them, and publishes what ships next. | | [Projects](/code/systems/projects) | System | Projects tracks each body of work toward a Goal: its Tasks and Issues, start and target date, triage and assignees. | | [Repositories](/code/systems/repositories) | System | Repositories holds a Startup’s code and definitions in db.sb, with branches, Changes, checks and Versions. | | [Status pages](/systems/status-pages) | System | Status pages publishes the health of each Product and opens an Incident when a check fails, updating subscribers until it resolves. | | [Incident response](/workflows/processes/incident-response) | Process | Incident response restores service first, fixes the cause second, and prevents the repeat third. | | [Onboarding](/workflows/processes/onboarding) | Process | Onboarding gets every new Customer to first value, by hand until the Startup automates each step. | | [Product definition](/workflows/processes/product-definition) | Process | Product definition turns each Offer into the Nouns and Verbs that every Interface is generated from. | | [Provider wiring](/systems/integrations/provider-wiring) | Process | Provider wiring connects a new Startup to the default provider of every capability it uses. | | [Release](/workflows/processes/release) | Process | Release takes each reviewed Change to all traffic in stages, with automatic revert. | | [Security](/workflows/processes/security) | Process | Security keeps every Permission earned, every secret fresh, and every access recorded. | | [Shipping](/workflows/processes/shipping) | Process | Shipping delivers the most valuable Change every day and prunes what nobody uses every week. | | [Close the loop](/workflows/processes/customer-research/close-the-loop) | Workflow | Close the loop tells each Customer whose Evidence a merged Issue addresses that it shipped, then grades whether they used it. | | [Design first run](/workflows/processes/product-definition/design-first-run) | Workflow | Design first run compiles sample records, empty states and the shortest path to an Offer’s activation event from the definition. | | [API Key](/business/nouns/api-key) | Noun | An API Key is a secret a Startup issues to one Customer, which signs that Customer’s calls to its API, SDK, CLI and MCP server. | | [App](/business/nouns/app) | Noun | An App is an Interface where people work with a Product’s Nouns and Verbs through screens, backed by its API. | | [Builder](/business/nouns/builder) | Noun | A Builder is a named part of api.sb that builds one side of a Startup; StartupBuilder directs SiteBuilder, SoftwareBuilder, ServiceBuilder, and SalesBuilder. | | [Credit Grant](/business/nouns/credit-grant) | Noun | A Credit Grant is a prepaid or promotional balance a Customer spends on a Startup’s metered Offers, checked before each call. | | [Dataset](/business/nouns/dataset) | Noun | A Dataset is a Product of curated Things of one Noun, with a promise that they are true. | | [Entitlement](/business/nouns/entitlement) | Noun | An Entitlement is what a Customer gets from an accepted Offer: a Verb on a Noun in its Tenant, optionally bounded by a Limit. | | [Flag](/business/nouns/flag) | Noun | A Flag is a switch, evaluated per Visitor, Customer, or request, that selects which copy or behavior they get. | | [Flow](/business/nouns/flow) | Noun | A Flow is an ordered path through an App’s Dashboards that takes one Persona from first run to an Offer’s activation Event. | | [Implementation](/business/nouns/implementation) | Noun | An Implementation is how an Interface, System, or Verb of a Product runs: managed by the platform, custom code on it, or external. | | [Incident](/business/nouns/incident) | Noun | An Incident is an Issue where an Interface or Site fails Customers in production, tracked from detection to postmortem. | | [Interface](/business/nouns/interface) | Noun | An Interface is how a person or an Agent reaches a Product: an API, MCP server, CLI, SDK, Site, or App. | | [Issue](/business/nouns/issue) | Noun | An Issue is a Task reporting a problem or request, such as a bug or a feature request, with a reporter and a triage step. | | [Member Directory](/business/nouns/member-directory) | Noun | A Member Directory is a Customer’s own list of people and groups, pushed into its Tenant so access follows employment. | | [Persona](/business/nouns/persona) | Noun | A Persona is a named type of person with a job to do, such as a buyer, a seller, or an admin of an App. | | [Product Template](/business/nouns/product-template) | Noun | A Product Template is a reusable definition of one kind of Product: what it sells, who supplies the work, who buys, and how it earns. | | [Publication](/business/nouns/publication) | Noun | A Publication is the branded package a Startup’s Customers use: Domain, Interfaces, packages, docs and Portal, compiled from its Brand and a Version. | | [Software](/business/nouns/software) | Noun | Software is a Product a Customer uses through Interfaces, from a headless API to a full App. | | [Source](/business/nouns/source) | Noun | A Source is something a Product draws on to keep its promise but did not build: owned, wrapped, or recruited. | | [SSO Connection](/business/nouns/sso-connection) | Noun | An SSO Connection links a Customer’s own identity system to its Tenant, so the Customer’s people sign in through it. | | [Standard](/business/nouns/standard) | Noun | A Standard is a spec an Interface conforms to, so a Startup may publish its Product’s Verbs in a shape outside callers already use. | | [Agent.mint](/business/nouns/agent/mint) | Verb | Mint creates an Agent in a Customer’s Tenant from an Agent Product the Customer bought. | | [APIKey.issue](/business/nouns/api-key/issue) | Verb | Issue creates an API Key for one Customer and returns its secret once; afterwards only the prefix shows. | | [APIKey.revoke](/business/nouns/api-key/revoke) | Verb | Revoke stops an API Key at once: its next call fails with 401, and the record and its history stay. | | [APIKey.roll](/business/nouns/api-key/roll) | Verb | Roll issues a replacement API Key with the same scope and keeps the old one working until a set time. | | [App.publish](/business/nouns/app/publish) | Verb | Publish releases an App to its Customers, so each Tenant runs its newest build. | | [Entitlement.check](/business/nouns/entitlement/check) | Verb | Check says whether a Customer may call a Verb now, how much of its Limit remains, when that resets, and which Offer lifts it. | | [Noun.retire](/business/nouns/noun/retire) | Verb | Retire removes a published Noun from new Versions; its records, its history and every pinned Version keep serving. | | [Noun.trace](/business/nouns/noun/trace) | Verb | Trace lists every Verb, Process, Offer, Dashboard and Version that references a Noun, so an edit or a retire shows its reach first. | | [Offer.grant](/business/nouns/offer/grant) | Verb | Grant adds an Entitlement to an Offer: a Verb its Customers may call, optionally bounded by a Limit. | | [Offer.subscribe](/business/nouns/offer/subscribe) | Verb | Subscribe accepts a recurring Offer as a Subscription that renews each period until it ends. | | [Order.fulfill](/business/nouns/order/fulfill) | Verb | Fulfill grants what an Order bought: Entitlements for software and data, a shipment for goods. | | [Problem.suggest](/business/nouns/problem/suggest) | Verb | Suggest records a Customer’s ask for something the Product lacks as Evidence on a Problem, with the asker attached. | | [Tenant.provision](/business/nouns/tenant/provision) | Verb | Provision creates a Customer’s Tenant in a Startup’s App, holding that Customer’s records apart from every other. | | [Verb.retire](/business/nouns/verb/retire) | Verb | Retire removes a published Verb from new Versions; callers pinned to earlier Versions keep calling it. | | [Version.deploy](/business/nouns/version/deploy) | Verb | Deploy points a Startup’s live address at a Version, so every Interface serves that build. | | [API](/code/api/reference) | Interface | The API serves every Verb and record of a Product over HTTPS, one route per operation, described by OpenAPI and agents.json. | | Chat app | Interface | A Chat app reaches a Product inside a chat workspace: its commands are the Product’s Verbs, and it ships through the workspace’s app directory. | | [CLI](/code/cli/reference) | Interface | The CLI runs every Verb from a shell, as a typed command per Verb or as `do Noun.verb` with JSON input. | | [MCP](/code/mcp/reference) | Interface | The MCP server gives any agent four tools, `search`, `fetch`, `try` and `do`, that reach every Verb through typed programs. | | [SDK](/code/sdk/reference) | Interface | The SDK is the typed client `$` that calls every Verb as `$.Noun.verb(input)`, in any Mode, scoped by `$.with`. | | Webhooks | Interface | Webhooks deliver each Event a Watch selects to an HTTPS endpoint, signed with the Standard Webhooks headers and retried until acknowledged. | ## Next steps - [Interfaces](/code/builders/software/interfaces): one Verb on every Interface. - [Agents](/products/agent/agents): sell an Agent, billed on its verdicts. - [Compatibility](/code/builders/software/compatibility): change a Live API without breaking a caller. # Interfaces URL: /code/builders/software/interfaces · Id: `page:code/builders/software/interfaces` > Every Product ships its Verbs through eight Interfaces, and each Verb keeps one name, one Action, and one set of rules on all of them. An [Interface](/business/nouns/interface) is how a person or an [Agent](/business/nouns/agent) reaches a [Product](/business/nouns/product). Every Product ships the same [Verbs](/business/nouns/verb) through eight: API, MCP, CLI, SDK, [Site](/business/nouns/site), [App](/business/nouns/app), docs, and webhooks. ## One Verb, every Interface Each Verb has one name, `Noun.verb`, on every Interface: the API route, the SDK method, the CLI command, the MCP call, and the webhook [Event](/business/nouns/event). Every Interface checks the same [Permissions](/business/nouns/permission) and [Limits](/business/nouns/limit), and every call returns the same [Action](/business/nouns/action). An Interface changes how a call reads, never what it does. Here is one Verb on every Interface. Pick an Interface in the header, and every example on the site follows. **Ask** ```text Qualify the latest lead with an offer. ``` **API** ```bash curl -X POST https://api.sb/shiftnote.app/leads/lead_1/qualify \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"offer":"offer_1"}' ``` ```json { "api": "https://api.sb/shiftnote.app", "deal": { "$id": "https://api.sb/shiftnote.app/deals/deal_1", "$type": "Deal", "status": "Open" }, "lead": { "$id": "https://api.sb/shiftnote.app/leads/lead_1", "$type": "Lead", "status": "new" }, "action": { "$id": "https://api.sb/shiftnote.app/actions/action_1", "operation": "Lead.qualify", "status": "done" }, "links": { "self": "https://api.sb/shiftnote.app/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const { deal, lead } = await $.Lead.qualify({ lead: 'lead_1', offer: 'offer_1' }) ``` **CLI** ```bash npx startup-builder do Lead.qualify --json '{"lead":"lead_1","offer":"offer_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Lead.qualify({ lead: 'lead_1', offer: 'offer_1' })" } } ``` ## What each Interface is for | Interface | Who uses it | What it gives them | | --- | --- | --- | | API | Any program | One HTTPS route per Verb, JSON in and out | | SDK | TypeScript code | Typed methods on `$`, from the `startup-builder` package | | CLI | Terminals, scripts, coding Agents | One `do` command per Verb, with JSON output outside a terminal | | MCP | Agents | A `do` call that runs a short program against the SDK | | Site | [Visitors](/business/nouns/visitor) and buyers | Public [Pages](/business/nouns/page) and [Offers](/business/nouns/offer) under the [Brand](/business/nouns/brand) | | App | Each [Persona](/business/nouns/persona) at work | Screens over the same Verbs | | docs | Developers and Agents | The contract in HTML and Markdown, generated from the definition | | webhooks | Other systems | Each Event, signed, as it happens | Docs are an Interface because they compile from the same definition. A Verb's reference cannot describe behavior the API lacks. ## Screens for people An App derives three screens from each [Noun](/business/nouns/noun). A list draws as a [`DataTable`](/code/ui/components/data-table) or a [`Board`](/code/ui/components/board), and a record as a [`ThingDetail`](/code/ui/components/thing-detail). Each Verb the Persona may run gets a [`VerbSheet`](/code/ui/components/verb-sheet). The first session opens on the onboarding checklist and ends at first value, as the [Product Template](/business/nouns/product-template) defines it: a shared gallery, a closed month. An empty list renders one sentence and the one Verb that fills it, such as `No galleries yet. Create gallery`, never a blank table. Every `pending` state has exactly one rendering, as [`ActionStatus`](/code/ui/components/action-status) defines. ## Each caller sees its own Verbs Authorization runs once, below every Interface, and narrows everything above it. A record's `actions` map lists only the Verbs this caller may run on it now. An Agent's MCP tool list holds only its [Role](/business/nouns/role)'s Permissions, and an App draws only the buttons its Persona may press. Two callers reading the same record can see different Verbs. Neither sees a Verb it would be refused. ## One address, three renderings Every record has one URL, its `$id`, and that URL answers in three forms. A browser gets HTML, code gets JSON, and an Agent sending `Accept: text/markdown` gets Markdown in fewer tokens. The data and the links are identical in all three. plugatlas.com, a map of EV chargers, declares a `Station` Noun: ```bash curl https://api.sb/plugatlas.com/stations/st_204 -H "Accept: text/markdown" ``` Every API also publishes four machine registers: an OpenAPI document, `llms.txt`, a Markdown copy of every page, and `agents.json`. An Agent reads the contract a developer reads, in the form it parses best. A new Verb appears in all four at its next deploy. ## Same call, different Product An HTTPS `POST` says little about the Product behind it. The Action it returns, and the Event the [Offer](/business/nouns/offer) earns on, say the rest. | Call | Product | The Action reports | Earns on | | --- | --- | --- | --- | | `Station.lookup` | [Dataset](/business/nouns/dataset) | `done`, with records naming their [Source](/business/nouns/source) and `refreshedAt` | The `done` Action | | `Swap.approve` | [Software](/business/nouns/software) | `done` with the new state, or `refused` naming the broken rule | The `done` Action | | `Period.close` by a bookkeeping Agent | Agent | `pending` with reason `running`, then `done` with the closed books | The [Evaluator](/business/nouns/evaluator)'s passing verdict | | `Order.place` for a vendor review | [Service](/business/nouns/service) | `pending` with reason `awaitingWorker` until the work is delivered | The [Customer](/business/nouns/customer)'s acceptance | A successful HTTP response never means the Customer got value. Clients read the Action's status, and webhooks deliver its Events. ## Addresses Every Interface answers on [api.sb](/code/platform/api-sb) under the [Startup](/business/nouns/startup)'s namespace, such as `https://api.sb/plugatlas.com`. Web Interfaces also mount on the Startup's own [Domain](/business/nouns/domain) at a path, such as `plugatlas.com/api`. The SDK and CLI need no path. A new hostname is another address for the same Product, never another Product. Its Customers, [Tenants](/business/nouns/tenant), and history stay where they are. ## Next [Composition](/products/composition) covers building one Product from others. # What Customers see URL: /code/builders/software/publication · Id: `page:code/builders/software/publication` > A Startup's Customers meet its Publication, the branded package of its Domain, Interfaces, packages, keys, docs, status page and Portal, and never the platform. A [Startup](/business/nouns/startup)'s [Customers](/business/nouns/customer) meet its [Publication](/business/nouns/publication): the [Domain](/business/nouns/domain), [Interfaces](/business/nouns/interface), packages, keys, docs, status page and [Portal](/business/nouns/portal) of each [Product](/business/nouns/product), under the Startup's own [Brand](/business/nouns/brand). Nothing inside a Publication names the platform. ## What a Customer meets A Customer of `transcribe.fm` installs the `transcribe` SDK, sets `TRANSCRIBE_API_KEY` and calls `transcribe.fm/api`. Each part comes from one field of the Publication: | What the Customer meets | Field | At transcribe.fm | | --- | --- | --- | | API | `api` | `https://transcribe.fm/api` | | MCP server | `mcp` | `https://transcribe.fm/mcp` | | Docs, with `llms.txt` and Markdown per page | `docs` | `https://transcribe.fm/docs` | | Status page | `statusPage` | `https://transcribe.fm/status` | | Portal: keys, usage, billing, [Tenant](/business/nouns/tenant) settings | `portal` | `https://transcribe.fm/portal` | | SDK, CLI and MCP packages | `packages` | `transcribe` in each package registry | | API keys | `keyPrefix` | `transcribe_sk_live_…` | | Key variable | `envPrefix` | `TRANSCRIBE_API_KEY` | | Webhook signature | `webhookHeader` | `Transcribe-Signature` | | Error types | `errorNamespace` | `https://transcribe.fm/errors/…` | The key prefix comes ahead of a fixed pattern, so secret scanners still recognize every leaked key from every Startup with one rule. The published OpenAPI document, SDK and MCP tool list carry only the [Verbs](/business/nouns/verb) a Customer may call. Operator Verbs such as [`Offer.publish`](/business/nouns/offer/publish) and [`Period.close`](/business/nouns/period/close) stay out, so a Customer's [Agent](/business/nouns/agent) spends no context on calls it cannot make. ## One address, two forms Each Interface answers at a path on the canonical Domain: `/api`, `/mcp`, `/docs`, `/portal`. `api.transcribe.fm` is an alias that serves the same API in place. The path is canonical because it needs nothing beyond the canonical Domain. It shares that Domain's certificate, works on a claimed name, and lets the Startup's [App](/business/nouns/app) call its API from the same origin. A Startup that wants the conventional `api.` host pins the alias, and no Customer's code breaks. A Customer's code and an Agent's MCP configuration hold the base address for years. So the address never changes after the first Customer holds it: a new Domain arrives as an alias, and a rebrand redirects. ## Nothing names the platform A Customer never sees `api.sb`, the platform's packages, its key variable or its signature header. The registry refuses a Publication whose fields carry any of them. Each Startup keeps `api.sb/` as its own namespace. Its [Workers](/business/nouns/worker), its `test` environment and its previews use it, and no Customer is ever given it. [StartupBuilder](/code/builders/startup) is the [Studio](/business/nouns/studio)'s own Publication, at `api.sb` with the `startup-builder` packages. So every tool a founder gets, from keys and usage to logs and the `test` environment, exists in each Startup's Publication for its own Customers. ## Compiled from a Brand and a Version A Publication compiles from the Brand and one [Version](/business/nouns/version). A restyle compiles a new Publication and leaves the API version alone, so the Brand changes without breaking a Customer's code. A Customer's path carries one version, on the Startup's own route. Moving the Startup to a buyer at a sale moves the Domain, and with it every address a Customer holds. ## Next - [Domains](/products/site/domains/site-domains): how a Startup gets, keeps and moves the names its Publication answers on. - [Interfaces](/code/builders/software/interfaces): one Verb on every Interface. - [SDK](/code/sdk): the packages a Publication names. # Actions and Modes URL: /code/builders/startup/actions-and-modes · Id: `page:code/builders/startup/actions-and-modes` > Every call to a Verb returns an Action, with a status, a reason while it waits, who acted for whom, the Mode the caller chose, and a hidden Function. Every call to a [Verb](/business/nouns/verb) returns an [Action](/business/nouns/action), whoever calls and whoever does the work. The Action carries a status, a reason while it waits, who acted for whom, and the [Mode](/business/nouns/mode) the caller chose. ## Every call returns an Action A well-formed, authenticated call always returns an Action. [Invalid input](/code/api/errors/invalid-input), an unknown Verb, or a missing key fail at the edge with a plain error and no Action. What the [Thing](/business/nouns/thing) decides is different. A wrong state, a spent [Limit](/business/nouns/limit), or a [Mandate](/business/nouns/mandate) out of scope returns an Action with status `refused`, its reason, and the [refused](/code/api/errors/refused) error. Take a [Startup](/business/nouns/startup) that closes the monthly books for small design studios. Its `Close.run` Verb reconciles a month of bank lines. Called by a client, by the Startup's own [Agent](/business/nouns/agent), or by a cron schedule, it returns the same Action. ## Who acted, for whom Every Action records `by`, the [Worker](/business/nouns/worker) that acted, and `for`, the party it acted on behalf of. When an Agent acts for someone else, the Action also names the Mandate that let it. An Agent acts in one of two ways. As itself, it uses the Startup's own accounts and identifies as an agent. For a [Human](/business/nouns/human), it acts under a Mandate scoped by [Channel](/business/nouns/channel), volume, topics, and Limits, and the Human is the author of record. The bookkeeping Startup's Agent emails a client's vendor as the client, under the client's Mandate. The Action reads `by: agent`, `for: client`, and names the Mandate. The client sees every message sent in their name, and pausing or revoking the Mandate takes effect at once. ## Five statuses An Action has one of five statuses. Every change of status appends an [Event](/business/nouns/event). | Status | Meaning | | --- | --- | | `pending` | Not finished. Its reason says why. | | `done` | Finished, with a result. | | `failed` | Finished, with an error. | | `canceled` | Stopped before it finished, by a caller, a watcher, or a deadline. | | `refused` | Never started: the state, a Limit, or a Mandate did not allow it. | A finished Action is final. A retry after `failed` is a new Action, linked to the one that failed. `done` is the doer's claim. Where a [Customer](/business/nouns/customer) must accept the result, acceptance is a separate Event, such as `Close.accepted`. The [Offer](/business/nouns/offer) bills on the Event it declares. ## Why an Action waits A `pending` Action always names its reason. `running` means the platform is executing; every `Awaiting` reason names who holds the work while nothing runs. | Reason | The Action waits for | | --- | --- | | `queued` | Capacity to start. | | `running` | Nothing: it is executing now. | | `retrying` | A failed step to run again after a backoff. | | `awaitingWorker` | A Worker to answer a [Task](/business/nouns/task), such as an [Approval](/business/nouns/approval). | | `awaitingInput` | The caller or a Customer to supply something. | | `awaitingSource` | An outside [Source](/business/nouns/source) to respond. | | `awaitingAction` | A child Action to finish. | | `awaitingTime` | A scheduled time or a delay window to pass. | An operator scanning a queue sees at once whether the platform is busy or a person is late. A month close stuck on `awaitingInput` is the client's missing receipt, not a slow server. ## Three Modes A Mode is how long the caller waits and whether the call is stored. Each Verb declares a default Mode and the Modes a caller may choose. ```ts import { $ } from 'startup-builder' const preview = await $.try.Period.close({ period: 'period_2026_09' }) // waits, stores nothing const action = await $.send.Period.close({ period: 'period_2026_09' }) // returns at once, status pending const period = await $.do.Period.close({ period: 'period_2026_09' }) // waits for the finished Action ``` `try` suits previews, quotes, and lookups, and has no side effects. `send` suits long work and steps a Human takes: the caller gets the `pending` Action and follows its Events. `do` holds the call until the Action finishes, and is the default for writes. The API takes `?mode=send` and answers `202` with the `pending` Action; the CLI takes `--send`. Every call in every Mode is metered as a usage Event, and nothing billed is ever sampled. ## Four kinds of Function A [Function](/business/nouns/function) is how a Verb executes. The caller never sees which kind runs, because every call returns the same Action. | Kind | Does the work | In the bookkeeping Startup | | --- | --- | --- | | `code` | Deterministic code. | Matches bank lines to invoices by amount and date. | | `generative` | A model that writes content or structured data. | Drafts the month-end summary for the client. | | `agentic` | An Agent taking steps with [Tools](/business/nouns/tool). | Chases an unmatched payment through the client's inbox. | | `human` | A Human, through a Task. | Signs a tax filing that the law reserves to a credentialed preparer. | Work goes to the cheapest kind that can do it. A miss or low confidence escalates one rung: code, then generative, then agentic, then human. Because the kind is invisible, a Startup moves a Verb between kinds without changing its API. The bookkeeping Startup first runs `Close.review` as a human Function. It moves the Verb to an agentic Function once the Agent's [Evaluator](/business/nouns/evaluator) verdicts agree with the reviewer on 95 percent of closes. No caller changes a line. ## Next [What a Startup sells](/products/four-kinds): the four kinds of [Product](/business/nouns/product), and how each one earns. # Actuating loops URL: /code/builders/startup/actuating-loops · Id: `page:code/builders/startup/actuating-loops` > Every measured loop names the Setting, budget or Limit its reading moves, so a number sets the next step instead of filling a report. Every loop sets the next step. Each measured [Process](/business/nouns/process) and [Play](/business/nouns/play) names the [Setting](/business/nouns/setting), spending budget or [Limit](/business/nouns/limit) its reading moves. ## How a loop actuates A loop names its [Metric](/business/nouns/metric), its window and its minimum sample. It also names what it actuates, and how the reading moves it. The verifier fails a measured Process or Play that actuates nothing. ## Spend state [Runway](/workflows/processes/runway) writes a [Forecast](/business/nouns/forecast) every week and after every large money [Decision](/business/nouns/decision). The latest Forecast sets the [Startup](/business/nouns/startup)'s `spendState`, and every money Limit reads it before a call. | `spendState` | When | Effect | | --- | --- | --- | | `free` | Default alive | Limits apply as set. | | `tight` | Default dead | Discretionary Limits halve, the [Demand Budget](/business/nouns/demand-budget) included. | | `hold` | Under 13 weeks of runway | One-way spend stops, and a Decision opens. | Inside that bound, the weekly mix of Plays moves the Demand Budget toward the Play with the best measured payback. ## Other loops - Customer health below its line starts a rescue in [Retention](/workflows/processes/retention). Use near an [Entitlement](/business/nouns/entitlement)'s bound starts an expansion. - An error group opens an [Issue](/business/nouns/issue), and the fix-an-issue [Workflow](/business/nouns/workflow) repairs it in a [Change](/business/nouns/change) preview. - A [Startup Template](/business/nouns/startup-template) rollout across the [Portfolio](/business/nouns/portfolio) halts when a guardrail Metric moves. - The founder's inbox ranks every ask by the expected value of answering it. ## Example A Startup holds $60,000 and burns a net $5,000 a week. The week's Forecast reads 12 weeks of runway, so `spendState` moves to `hold`. A $4,000 sponsorship is one-way spend, so it waits as a Decision for the [Founder](/agents/founding/founder), while a $40 API call still runs. # The Startup as code URL: /code/builders/startup/business-as-code · Id: `page:code/builders/startup/business-as-code` > A Startup is a definition plus a loop that keeps it true, built on five pillars from the model to composition, each a set of files and calls. A [Startup](/business/nouns/startup) is a definition plus a loop that keeps the running business true to it. Each of the five pillars below is a set of files, records and calls. ## The model: Nouns, Verbs and Events A [Noun](/business/nouns/noun) is a type of record: its properties, its [Relationships](/business/nouns/relationship), and the [Verbs](/business/nouns/verb) that act on it. A [Thing](/business/nouns/thing) is one instance, with a stable id, a current state, and the properties of its Nouns. Take a Startup that sells lesson booking to independent music teachers. It declares a `Lesson` Noun in `nouns/Lesson.mdx`, with a `student`, a `startsAt` and a `status`. Every lesson a teacher books is a Thing at an address such as `https://api.sb/lessons.example/lessons/lsn_42`. A Verb is what can be done to a Noun. Each Verb has six forms, and every [Interface](/business/nouns/interface) uses the same six: | Name | Example | Where it appears | | --- | --- | --- | | verb | `books` | Prose: a parent books a `Lesson`. | | action | `book` | The call: `Lesson.book`. | | activity | `booking` | The state while the [Action](/business/nouns/action) runs. | | event | `booked` | The [Event](/business/nouns/event): `Lesson.booked`. | | reverse | `bookedBy` | The record read backward: who booked it. | | inverse | `cancel` | The Verb that undoes it. | An [Action](/business/nouns/action) is one Verb performed by a [Worker](/business/nouns/worker) on a Thing. An [Event](/business/nouns/event) is the immutable record of what happened, such as `Lesson.booked`. Actions change; Events never do. State is [computed from Events](/code/builders/startup/computed-state), never set by hand. The view of any scope reads the same records, addressed by a [view address](/code/views/view-address) and rendered by a [Dashboard](/business/nouns/dashboard) as Markdown, screens or JSON. ## The loop: Goals, Experiments and Decisions A [Goal](/business/nouns/goal) holds [Key Results](/business/nouns/key-result) read live from [Metrics](/business/nouns/metric), and every Startup holds one: its [Minimum Success Criteria](/business/nouns/minimum-success-criteria). The [weekly test](/business/weekly-test) ranks the gap and runs one [Experiment](/business/nouns/experiment) on the weakest slot of the [Founding Hypothesis](/business/founding-hypothesis). A file in [`experiments/`](/code/file-conventions/experiments) is one Experiment: the [Hypothesis](/business/nouns/hypothesis), the value it varies, and the Metrics that pick the winner. Each measured [Process](/business/nouns/process) names the [Setting](/business/nouns/setting), budget or [Limit](/business/nouns/limit) its reading moves, as [actuating loops](/code/builders/startup/actuating-loops) shows. Every run ends in [Evidence](/business/nouns/evidence) and a [Decision](/business/nouns/decision). [The experiment guide](/code/run-an-experiment) takes one from a file to a Decision. ## Authority: Permissions, Limits and Mandates Every Action records who acted (`by`), for whom (`for`), and under which [Mandate](/business/nouns/mandate). A [Role](/business/nouns/role) file declares its contract in [`agents/`](/code/file-conventions/roles): its `limits`, its `mandates`, and its `autonomy` rung, `assist`, `supervised` or `full`, per decision class. Every Limit is checked before the call runs. A call over its Limit does not fail: it returns a `pending` Action with reason `awaitingAction`, held by an [Approval](/business/nouns/approval). Approved, it runs; refused, it ends `refused`; unanswered by its deadline, it ends `canceled`. Limits inherit, and a child only tightens. [Mandates and limits](/agents/mandates-and-limits) lists where each one lives. ## Rehearsal and change: Modes, Changes and Versions A call picks its [Mode](/business/nouns/mode). `try` runs and stores nothing, `send` returns a `pending` Action at once, and `do` waits for the result, as [Modes](/code/api/guides/modes) shows. The `test` environment runs the same definition with simulated payments, ad spend and filings, as [test and live](/code/builders/startup/test-and-live) explains. Nobody edits a live definition in place. Every edit is a [Change](/business/nouns/change): writes previewed on a branch, checked, approved where a Limit requires it, and merged as one unit. No author approves their own Change. Each merge produces a new [Version](/business/nouns/version) at a fingerprint. An [Order](/business/nouns/order) keeps the Version of the [Offer](/business/nouns/offer) it bought, so a price Change never rewrites a past sale. [Ship my changes](/code/ship-my-changes) takes a Change from review to the live address. ## Composition: inheritance and projection A [Startup Template](/business/nouns/startup-template) is a definition other Startups extend, overriding only what differs. The root of the [catalog](/start/templates) carries [Teams](/business/nouns/team), [Systems](/business/nouns/system), Processes and Offers. The lesson-booking Startup declares its `Lesson` Noun and its Offers, and inherits the rest. A Startup pins the Version it extends. When the Startup Template improves, the upgrade arrives as a Change the Startup reviews, never as a silent rewrite. Below the template, a Noun inherits another's properties, and a Thing can be several Nouns at once. A [Dataset](/business/nouns/dataset) served through an API is also [Software](/business/nouns/software), with the properties of both. Each Verb projects to an API route, an SDK method, a CLI command, an MCP call and an Event, all named `Noun.verb`: **Ask** ```text Place the latest order with an offer. ``` **API** ```bash curl -X POST https://api.sb/ledgerlark.com/orders/place \ -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"offer":"offer_1"}' ``` ```json { "api": "https://api.sb/ledgerlark.com", "order": { "$id": "https://api.sb/ledgerlark.com/orders/order_1", "$type": "Order", "total": { "amount": 400, "currency": "USD" }, "status": "placed" }, "action": { "$id": "https://api.sb/ledgerlark.com/actions/action_1", "operation": "Order.place", "status": "done" }, "links": { "self": "https://api.sb/ledgerlark.com/actions/action_1" } } ``` **SDK** ```ts import { $ } from 'startup-builder' const order = await $.Order.place({ offer: 'offer_1' }) ``` **CLI** ```bash npx startup-builder do Order.place --json '{"offer":"offer_1"}' ``` **MCP** ```json { "name": "do", "arguments": { "code": "return await $.Order.place({ offer: 'offer_1' })" } } ``` One write adds a Verb's endpoint, SDK method, agent tool, [App](/business/nouns/app) button and reference row. ## Next [What happens on every call](/code/builders/startup/actions-and-modes) follows one Action from the call to its last Event. [Business-as-Code](/business/business-as-code) states the five pillars for founders. # Computed state URL: /code/builders/startup/computed-state · Id: `page:code/builders/startup/computed-state` > A Startup's state is computed from Events and never set by hand, so a status, a fit or a payback cannot go stale. State is computed from [Events](/business/nouns/event), never set by hand. A computed property names the Events it reads and no [Verb](/business/nouns/verb) can write it, so it cannot go stale. ## How it works A computed property lists the Events it reads. The platform recomputes it when one arrives, and the verifier fails any Verb that takes it as an input or sets it in an effect. The usual failure is a field someone forgets to update: a stage, a win probability, a runway cell. A computed field has no one to forget it. ## Where it runs | Property | Computed from | | --- | --- | | [Customer](/business/nouns/customer) `status` | `Offer.subscribed`, `Customer.activated`, `Subscription.unsubscribed`, `Subscription.renewed` and `Order.placed`; `atRisk` reads Customer health. | | [Lead](/business/nouns/lead) `fit` | The Lead fit [Policy](/business/nouns/policy), graded `strong`, `partial` or `none`. | | [Deal](/business/nouns/deal) `statusSince` | The Deal's own Events. | | [Renewal](/business/nouns/renewal) `outcome` | The [Subscription](/business/nouns/subscription)'s Events at the end of its term. | | [Play](/business/nouns/play) `paybackDays` | Posted [Entries](/business/nouns/entry) and collected [Invoices](/business/nouns/invoice), walked back through each Customer's [Acquisition](/business/nouns/acquisition). | A Deal's probability defaults from the [Portfolio](/business/nouns/portfolio)'s measured conversion for the same [Motion](/business/nouns/motion), Deal size and time in stage. It shrinks toward the [Startup](/business/nouns/startup)'s own history as that grows. ## Sealed readings A number an investor reads cites a [Proof](/business/nouns/proof): the [Metric](/business/nouns/metric), its value, the Policy that computed it and the log root. Verifying the Proof reruns the query against the log root and returns the same value, or the Proof fails. ## Example A Customer subscribes, and `Offer.subscribed` makes the status `trialing`; two days later `Customer.activated` makes it `activated`. Three silent weeks drop Customer health below its line, the status reads `atRisk`, and [Retention](/workflows/processes/retention) starts a rescue. No [Worker](/business/nouns/worker) ever wrote the field. # Cost per Action URL: /code/builders/startup/cost-per-action · Id: `page:code/builders/startup/cost-per-action` > Every Action settles a Cost that rolls up per Verb, Offer and Customer, so unit economics and price floors read the same rows. Every [Action](/business/nouns/action) settles a [Cost](/business/nouns/cost), and Costs roll up per [Verb](/business/nouns/verb), [Offer](/business/nouns/offer) and [Customer](/business/nouns/customer). Unit economics, [Price](/business/nouns/price) floors and margin work all read the same rows. ## What an Action records Each Action records a span with its parent Action, so the calls a [Workflow](/business/nouns/workflow) makes form one trace. When it finishes, it settles a Cost for each kind of work it used: compute, model tokens, upstream calls and human minutes. Each Verb declares the kinds of Cost its Actions settle, so the rollup knows what to expect before the first call. ## Reserve, settle, release A call an outside service prices reserves its worst case before it runs. That is the quoted maximum of every attempt it may be charged for, misses included. The [Limit](/business/nouns/limit) check reads the reservation, so concurrent calls never commit more than the Limit allows. The call settles at its actual Cost, one Cost per charged attempt, and the unused reservation is released at once. A Cost above the reservation is recorded in full with its overrun, and an overrun past a Limit opens an [Approval](/business/nouns/approval). A lookup reserves $0.05, its quoted maximum across two upstreams. The first misses and charges $0.01, the second answers for $0.03, and the Action settles two Costs and releases $0.01. ## Costs fall on their own An agentic [Function](/business/nouns/function) converges when its traces show the same tool sequence and output shape, with an [Evaluator](/business/nouns/evaluator) pass rate of 95% or more. The [Engineering Lead](/agents/engineering/engineering-lead) then distills a code Function from them. The code Function arrives as a [Change](/business/nouns/change) that replays recorded Actions as its regression suite. It runs first in the Verb's cascade with the agentic Function as fallback, and the Cost per call drops to compute. ## Example ```json { "$type": "Cost", "action": "action_7", "kind": "upstream", "attempt": 2, "amount": { "amount": 0.03, "currency": "USD" } } ``` # Experimentation URL: /code/builders/startup/experimentation · Id: `page:code/builders/startup/experimentation` > Every change a Startup makes runs as an Experiment, and the winning variant becomes the definition that later Startups inherit. A [Startup](/business/nouns/startup) runs each change as an [Experiment](/business/nouns/experiment): a [Hypothesis](/business/nouns/hypothesis) goes in, variants run against a [Metric](/business/nouns/metric), and a [Decision](/business/nouns/decision) comes out. The winner becomes the definition, and the [Studio](/business/nouns/studio) runs the same loop across its [Portfolio](/business/nouns/portfolio). ## Every run is a loop Experimentation is the resting state of a Startup, not a program someone starts. Every [Play](/business/nouns/play) run carries a loop, and so does every [Process](/business/nouns/process) run that reaches a [Customer](/business/nouns/customer) or a prospective one. The loop names a Hypothesis, a Metric with a window and a minimum sample, and a learn step that no definition can remove. The learn step records [Evidence](/business/nouns/evidence) and a Decision: ship, kill, or iterate. On iterate, it drafts the next variant as a proposed [Change](/business/nouns/change). A Process with nothing to learn, such as a month-end close, declares no loop and cites the control it serves. Everything else learns by default, so a Startup that sends, publishes, or sells is always testing something. ## What varies Any value a Startup owns can hold variants in place of one answer. A [Flag](/business/nouns/flag) assigns each unit its variant by a keyed hash, so a [Visitor](/business/nouns/visitor) sees the same headline on every visit. | What varies | Example | Unit | Pinned on | | --- | --- | --- | --- | | [Offer](/business/nouns/offer) terms | a 14-day trial with no card | Visitor | the [Order](/business/nouns/order) | | [Price](/business/nouns/price) | $29 against $39, as sibling Offers | new Customer | the Order | | [Page](/business/nouns/page) copy | a headline that names the [Problem](/business/nouns/problem) | Visitor | the [Contact](/business/nouns/contact) at signup | | [Message](/business/nouns/message) | a cold email subject line | Contact | the [Sequence](/business/nouns/sequence) | | Play mix | spend split between two Plays | Startup | the week's budget | | [Agent](/business/nouns/agent) behavior | a [Role](/business/nouns/role) agent's instructions or [Skill](/business/nouns/skill) | [Conversation](/business/nouns/conversation) | the [Action](/business/nouns/action) | | [Interview](/business/nouns/interview) script | the opening question | Contact | the Interview | An [Exposure](/business/nouns/exposure) is recorded when a variant is consumed: rendered, sent, charged, or run. A Metric counts only from first exposure. Agent behavior clears two gates before any Customer sees it. A candidate first passes its [Evaluators](/business/nouns/evaluator) offline at no worse than the current version, then runs in shadow on live inputs with no one-way Actions. Only then does it run online. ## Stakes choose the method The stakes of the value being varied decide how it is tested and who ships the winner. | Stakes | Examples | How it runs | Ship waits | | --- | --- | --- | --- | | Low | copy, send time, onboarding order | a bandit that shifts traffic to the leader | nothing: any agent ships | | Moderate | trial length, signup gate, agent instructions | a pre-registered sequential test | one business hour | | High | Price, refund [Limits](/business/nouns/limit), Offer terms | a fixed or sequential test, never a bandit | one business day, or an [Approval](/business/nouns/approval) below full autonomy | | Never | legal floor, [Consent](/business/nouns/consent), AI disclosure, refund rights, identity | none: the Change is refused | not applicable | [Delay windows](/agents/autonomy-levels/delay-windows) hold the decision, not the exposure, and [watchers](/agents/autonomy-levels/watchers) can pause or cancel inside them. Guardrail Metrics stop an Experiment the moment one breaches, and the control returns to every unit. Guardrail stops never wait, and anyone with access can stop any Experiment. An agent never varies its own yardstick. The Metric definitions, Evaluators, and guardrails that judge an Experiment are fixed for the agent that runs it. Price gets the strictest rule. Two Customers in one market never see different prices for the same Offer at the same moment. A price test runs as a sibling Offer for new Customers, by region, or in alternating weeks. ## Small traffic A new Startup with 40 Visitors a week cannot settle a split test in any useful time. Three moves give it a verdict anyway: - **Ask the Portfolio first.** Sibling Startups with the same [Product Template](/business/nouns/product-template), [Motion](/business/nouns/motion), and [Lifecycle](/business/nouns/lifecycle) state have already learned things, and their results open every new test. - **Pool across siblings.** Sibling Startups testing the same value read as strata of one Experiment. - **Take the cheapest decisive test.** A deposit page settles in two weeks what a split test settles in a quarter. [Test demand](/workflows/processes/test-demand) lists the rungs. Every number prints its readability, such as "Visitor to deposit: 37 of 200 exposures, readable in 9 days." A Startup never ships a high-stakes winner on a number that cannot be read. ## Winners become the definition Shipping writes one Change where the Experiment sat, replacing the Flag with the winning value. A Startup's own Experiment changes its own definition. A Studio Experiment on a default writes a new [Version](/business/nouns/version) of the [Startup Template](/business/nouns/startup-template). Losing variants are killed and kept: their exposures and Evidence stay on the record forever. The Hypothesis moves to `Supported` or `Refuted`, which stops the next agent from testing it again. The Decision records its premise: the measured effect and the conditions it held under. When traffic grows, the buyer mix shifts, or a year passes, the premise lapses. The shipped value then becomes the control of a new Experiment. A sales-tax API for developers tests two docs pages: one opens with a request example, the other with a pricing table. The request example lifts signups from 3.1% to 4.4% over 2,100 Visitors. It ships, and its Decision notes that it held for b2d traffic from search. ## The Studio runs the same loop One level up, the variants are whole Startups, Startup Template defaults, and Play Versions. An [Idea](/business/nouns/idea) spawns three to five sibling Startups as one Experiment. Each varies the riskiest part of its Hypothesis, such as the [ICP](/business/nouns/icp), the approach, or the price band. Each opens a [reserve page](/code/builders/startup/wants) on day one. Deposits decide. The winner is promoted, and the others go Dormant, kept and revivable. A Play rolls out by [Cohort](/business/nouns/cohort): 1%, then 10%, 50%, and all, with a control Cohort kept on the prior Version for the whole run. A guardrail breach reverts every write the Play made, in every Startup, in one query. Winning variants flow back into Startup Template defaults, so every new Startup starts from the best known version. Each default records the Experiment that set it and becomes the control of the next one. Speed is local and rigor is global: a write to a shared default first passes a Portfolio-wide false-discovery check. The Studio also keeps a program holdout: a small share of Startups stays on the root defaults for a quarter. Their results measure whether experimenting pays. ## Next - [Test demand](/workflows/processes/test-demand): the cheapest test that settles each Hypothesis. - [Wants](/code/builders/startup/wants): unmet demand as Evidence, and deposits before building. - [Office hours](/workflows/processes/office-hours): where the week's Decision is written. - [Experiments](/systems/experiments): the [System](/business/nouns/system) that runs every Experiment. - Plays, cohorts, and experiments: the Studio's side of the loop. # StartupBuilder URL: /code/builders/startup · Id: `product:startup-builder` > StartupBuilder turns an Idea into an operating Startup with SiteBuilder, SoftwareBuilder, ServiceBuilder, and SalesBuilder. StartupBuilder turns an [Idea](/business/nouns/idea) into a running [Startup](/business/nouns/startup). The Startup is one definition: [api.sb](/code/platform/api-sb) serves it, [Agents](/business/nouns/agent) operate it, and its owners steer it. StartupBuilder ## What it does StartupBuilder holds the Startup's definition and directs the four other [Builders](/business/nouns/builder) that build its parts. All five share one set of records. A [Price](/business/nouns/price) changed once is the price on the [Site](/business/nouns/site), in the API, and on the next [Invoice](/business/nouns/invoice). A new Startup starts from a [Startup Template](/business/nouns/startup-template): an [operating model](/agents/operating-model), one or more [Product Templates](/business/nouns/product-template), and the [Motions](/business/nouns/motion) they sell through. It arrives complete, with a [Brand](/business/nouns/brand), [Offers](/business/nouns/offer), a Site, every [System](/business/nouns/system) on shared data, and an Agent seated in each [Role](/business/nouns/role). StartupBuilder then runs it through its [Lifecycle](/business/nouns/lifecycle), from Idea to Live and on to Scale. [Processes](/business/nouns/process) wake on [Events](/business/nouns/event), and every [Action](/business/nouns/action) records who acted, for whom, and under which [Mandate](/business/nouns/mandate). Any [Change](/business/nouns/change) can run as an [Experiment](/business/nouns/experiment), and a [Studio](/business/nouns/studio) runs the same machinery across a [Portfolio](/business/nouns/portfolio). ## Built from - [SiteBuilder](/code/builders/site) - [SoftwareBuilder](/code/builders/software) - [ServiceBuilder](/code/builders/service) - [SalesBuilder](/code/builders/sales) - [api.sb](/code/platform/api-sb) ## Surfaces Three [Apps](/business/nouns/app) run StartupBuilder: - startups.studio is where founders and operators build and run Startups, from one Startup to a whole Portfolio. - [startups.new](/start/startups-new) creates a Startup from one sentence and opens it in startups.studio. - startup.games shows a founder's progress as quests and streaks. Four [Interfaces](/business/nouns/interface) reach the same [Verbs](/business/nouns/verb) under the same names: the [API](/code/api), [SDK](/code/sdk), [CLI](/code/cli), and [MCP](/code/mcp). One command scaffolds a Startup as a project ([details](/code/create-startups)): ```bash npm create startups ``` ## Next steps - [Vision](/code/builders/startup/vision): why a business runs as a program. - [The Startup as code](/code/builders/startup/business-as-code): the model every definition is written in. - [What every call returns](/code/builders/startup/actions-and-modes): statuses, reasons, and the three ways to call. - [What a Startup sells](/products/four-kinds): four kinds, who supplies them, and how each earns. - [Operating models](/agents/operating-model): what changes as humans join. - [Principles](/code/builders/startup/principles): seven rules the platform enforces. Everything StartupBuilder covers, generated from the registry: | Term | Kind | Definition | | --- | --- | --- | | [StartupBuilder](/code/builders/startup) | Product | StartupBuilder turns an Idea into an operating Startup with SiteBuilder, SoftwareBuilder, ServiceBuilder, and SalesBuilder. | | [startups.new](/start/startups-new) | Product | startups.new creates a Startup from one sentence and opens it in startups.studio. | | [Founding Team](/agents/founding) | Team | The Founding Team decides what the Startup pursues: its Idea, its strategy, its Goals, and every call escalated to it. | | [Legal Team](/agents/legal) | Team | The Legal Team keeps the Startup lawful: Agreements, privacy and Consent from day one, screening of every Offer, and every Reserved Act. | | [People Team](/agents/people) | Team | The People Team staffs every Role: it names an Agent for each one, recruits the Humans the law or the Startup needs, and pays them. | | [Product Team](/agents/product) | Team | The Product Team decides what gets built and why: Product definitions, list Prices and packaging, the build list, and the Site’s Pages for each ICP. | | [Quality Team](/agents/quality) | Team | The Quality Team checks all work: the checks inside each Process, every outbound Message, and every money move, with verdicts, never Approvals. | | [Building](/business/lifecycle/states/building) | Lifecycle state | Building is the state of a Startup whose Agents build its Brand, Products, Offers, site, API, and MCP server from its template. | | [Dormant](/business/lifecycle/states/dormant) | Lifecycle state | Dormant is the state of a Startup with no work running on it, whose records, site, and domain stay kept until it returns to Live. | | [Graduate](/business/lifecycle/states/graduate) | Lifecycle state | Graduate is the state of a Startup that leaves its studio for a company of its own, keeping its Brand, Customers, and records. | | [Hold](/business/lifecycle/states/hold) | Lifecycle state | Hold is the state of a Startup that keeps operating and serving Customers while its owner adds no new investment. | | [Idea](/business/lifecycle/states/idea) | Lifecycle state | Idea is the state of a Startup that states its Idea and who pays, before any build work starts. | | [Live](/business/lifecycle/states/live) | Lifecycle state | Live is the state of a Startup that is publicly reachable and takes money from Customers for at least one Offer. | | [Scale](/business/lifecycle/states/scale) | Lifecycle state | Scale is the state of a Startup that compounds: Customers stay and expand, demand comes from several sources, and margins hold. | | [Sell](/business/lifecycle/states/sell) | Lifecycle state | Sell is the state of a Startup whose owner has agreed to sell it, with its Brand, domain, Customers, and records. | | [Agent-run services firm](/start/templates/agent-run-services) | Startup Template | An Agent-run services firm runs with no humans and sells warranted outcomes as Services-as-Software, with the Agent behind them for hire. | | [Autonomous agent business](/start/templates/autonomous-agent) | Startup Template | An Autonomous agent business runs with no humans and sells Agent as a Service to businesses, people, and other Agents. | | [Autonomous data API](/start/templates/autonomous-data-api) | Startup Template | An Autonomous data API runs with no humans and sells a Dataset API and Headless SaaS to developers and their Agents. | | [Autonomous directory](/start/templates/autonomous-directory) | Startup Template | An Autonomous directory runs with no humans and sells listings in a Directory to Organizations that want buyers and Agents to find them. | | [Autonomous storefront](/start/templates/autonomous-storefront) | Startup Template | An Autonomous storefront runs with no humans and sells physical goods as a Dropship store to people and the Agents that shop for them. | | [Founder-led marketplace](/start/templates/founder-marketplace) | Startup Template | A Founder-led marketplace has one Human founder who signs for a Marketplace, while Agents recruit Suppliers and serve buyers. | | [Licensed professional network](/start/templates/licensed-network) | Startup Template | A Licensed professional network extends the Founder-led marketplace into a Licensed-human marketplace that buyers and their Agents book. | | [Managed service firm](/start/templates/managed-service-firm) | Startup Template | A Managed service firm extends the Agent-run services firm with Humans who share Roles and an E2E managed service for businesses. | | [Solo SaaS](/start/templates/solo-saas) | Startup Template | A Solo SaaS has one Human founder and Agents in every other Role, selling SaaS and its Headless SaaS to businesses and people. | | [Autonomous](/agents/operating-models/autonomous) | Operating model | Autonomous is the operating model with no humans: Agents fill every Role, and one-way decisions wait out a delay window before they proceed. | | [Multi-human](/agents/operating-models/multi-human) | Operating model | Multi-human is the operating model where several Humans share Roles with Agents, each Human working under their own Mandate and Limits. | | [Single human](/agents/operating-models/single-human) | Operating model | Single human is the operating model with one Human, a working CEO or a passive board chair, and Agents in every other Role. | | [Corporate records](/systems/corporate-records) | System | Corporate records keeps the legal Company behind a Startup: formation, officers, registered office, filings, board resolutions and good standing. | | [Discovery](/business/discovery) | System | Discovery runs buyer research: Interviews, Problems, graded Evidence, ICPs and Personas, so every Offer starts from what buyers said. | | [Documents](/code/systems/documents) | System | Documents keeps every versioned Document, deck or sheet, generated from records and rendered to the web, PDF, slides or spreadsheets. | | [Equity](/systems/equity) | System | Equity is the core System that keeps the cap table of each Company: shares, SAFEs, options and their holders, grants, vesting and conversions. | | [Experiments](/systems/experiments) | System | Experiments tests Hypotheses by varying copy, Price or behavior through Flags and decides each winner from primary and guardrail Metrics. | | [Goals](/business/goals) | System | Goals records what each Thing is trying to achieve: its Goals, Key Results read from Metrics, and the Decisions behind them. | | [Hiring](/systems/hiring) | System | Hiring fills open Roles with Humans: postings, candidates, screening calls held as Meetings, assessments and employment Agreements. | | [Intellectual property](/systems/intellectual-property) | System | Intellectual property keeps a Startup’s trademarks, patents, Domains and handles as one register, with deadlines and renewals watched. | | [Ledger](/systems/ledger) | System | Ledger is the double-entry book of record: Entries posted from Events, reconciled to Transactions, and closed each Period into statements. | | [Pay runs](/systems/payroll) | System | Pay runs keeps each employee’s pay record, prepares every run with withholding and deductions, and posts it to the Ledger. | | [Product analytics](/systems/product-analytics) | System | Product analytics turns the Visits and Events captured on every Domain and API into the conversion, activation and retention Metrics every Team reads. | | [Reports](/systems/reports) | System | Reports arranges saved Metric queries into Dashboards, weekly reviews and investor updates, delivered on a schedule and watched for thresholds. | | [Spend management](/systems/spend) | System | Spend management controls money going out: budgets, bills, expenses and cards issued on Stripe, each paid against Limits and spend states. | | [Surveys](/systems/surveys) | System | Surveys measures sentiment, such as NPS, CSAT and the product-market-fit question, and turns every answer into Metrics and Evidence. | | [Tax](/systems/tax) | System | Tax calculates and collects sales tax and VAT, tracks registrations, and prepares every return and information return. | | [Treasury](/systems/treasury) | System | Treasury holds a Startup’s cash accounts and balances on Stripe, moves money between them, and forecasts runway. | | [Workforce](/systems/workforce) | System | Workforce keeps every Worker, Human or Agent: the Roles they fill, their Teams, Skills, onboarding, assessments and offboarding. | | [Customer research](/workflows/processes/customer-research) | Process | Customer research learns from what buyers did and paid, never from their predictions. | | [Founder Run](/code/founder-run) | Process | Founder Run walks every Startup Template through its published Interfaces in test, as a synthetic founder and buyers, and records each step that stops. | | [Iteration](/workflows/processes/iteration) | Process | Iteration improves the Startup one change at a time: one number, the worst step, and one change a week. | | [Role review](/workflows/processes/role-review) | Process | Role review checks every filled Role against its contract each week and turns each missed result into a Decision. | | [Runway](/workflows/processes/runway) | Process | Runway tells the Founder every week whether the Startup reaches profit before its cash runs out. | | [Staffing](/workflows/processes/staffing) | Process | Staffing fills every Role in a Startup with an Agent by default and a Human where one is required. | | [Strategy](/workflows/processes/strategy) | Process | Strategy keeps the Startup’s ambitions, focus, and positioning true to its Evidence. | | [Owned following](/workflows/plays/owned-following) | Play | Owned following grows a niche newsletter, community and shared accounts in a Studio media Startup and lends its slots to siblings by expected value. | | [Reserve drop](/workflows/plays/reserve-drop) | Play | Reserve drop opens refundable deposits for 72 hours after one creator post and moves the Startup to Building only if deposits cross the entry check. | | [Agreement](/business/nouns/agreement) | Noun | An Agreement is a contract between two or more Parties, with its term, liability, and economics, that travels with the Startup. | | [Builder](/business/nouns/builder) | Noun | A Builder is a named part of api.sb that builds one side of a Startup; StartupBuilder directs SiteBuilder, SoftwareBuilder, ServiceBuilder, and SalesBuilder. | | [Cohort](/business/nouns/cohort) | Noun | A Cohort is a set of Startups that receives one Version of a shared definition, or one step of a Play, at the same time. | | [Company](/business/nouns/company) | Noun | A Company is a legal entity that holds Startups, signs Agreements, and owns equity, authority, and profit rights. | | [Evidence](/business/nouns/evidence) | Noun | Evidence is a recorded quote, reading, or artifact that supports or refutes a claim, graded as behavior, commitment, or opinion. | | [Experiment](/business/nouns/experiment) | Noun | An Experiment is a test of a Hypothesis that varies copy or behavior through Flags and judges the variants by a primary Metric. | | [Exposure](/business/nouns/exposure) | Noun | An Exposure is the moment one unit meets the Variant its Flag assigned, logged with every option and its propensity. | | [Forecast](/business/nouns/forecast) | Noun | A Forecast is a dated week-by-week projection of a Startup’s cash, revenue and Cost, computed from its records, that sets its spend state. | | [Goal](/business/nouns/goal) | Noun | A Goal is what a Thing is trying to achieve: an objective with one or more Key Results. | | [Human](/business/nouns/human) | Noun | A Human is a Worker who is a person, acting on Tasks through Apps, Mailboxes, and Channels. | | [Hypothesis](/business/nouns/hypothesis) | Noun | A Hypothesis is a belief about a Startup stated so it can be proved wrong, with the Metric and threshold that settle it. | | [ICP](/business/nouns/icp) | Noun | An ICP is the ideal customer profile a Startup is built to win: who they are and what they do. | | [Interview](/business/nouns/interview) | Noun | An Interview is one person’s pass through a question script, led by an Agent, whose answers become Evidence. | | [Key Result](/business/nouns/key-result) | Noun | A Key Result is one measurable target inside a Goal: a Metric, a baseline, a target, and a deadline. | | [Lifecycle](/business/nouns/lifecycle) | Noun | A Lifecycle is the states a Thing of one Noun moves through and the Verbs that move it between them. | | [Minimum Success Criteria](/business/nouns/minimum-success-criteria) | Noun | Minimum Success Criteria is the one number a Startup must reach by a date to stay worth running: a Goal the Founder sets once. | | [Persona](/business/nouns/persona) | Noun | A Persona is a named type of person with a job to do, such as a buyer, a seller, or an admin of an App. | | [Policy](/business/nouns/policy) | Noun | A Policy is a ruling a Startup declares on how its numbers are computed or its choices made, such as revenue recognition. | | [Portfolio](/business/nouns/portfolio) | Noun | A Portfolio is a managed set a Thing allocates attention and money across, by membership: a Studio’s Startups, a Startup’s child Startups, or its Products. | | [Problem](/business/nouns/problem) | Noun | A Problem is what an ICP struggles with, in their own words: how they solve it today and what it costs them. | | [Project](/business/nouns/project) | Noun | A Project is a body of work toward a Goal: its Tasks and Issues, a start, and a target date. | | [Readout](/business/nouns/readout) | Noun | A Readout is an Experiment’s result per Variant on its Metric, with the sample size, the interval, and how far the number can be trusted. | | [Role](/business/nouns/role) | Noun | A Role is a seat that owns a set of work and holds the Permissions to do it, filled by a Human or an Agent. | | [Startup Template](/business/nouns/startup-template) | Noun | A Startup Template is an operating model, one or more Product Templates, and the Motions they sell through, which a new Startup starts from. | | [Story](/business/nouns/story) | Noun | A Story is the customer narrative for one ICP, compiled from its Founding Hypothesis and Interview quotes, never written by hand. | | [Studio](/business/nouns/studio) | Noun | A Studio is an organization that builds Startups, holds them through Companies, and runs Plays across its Portfolio. | | [System](/business/nouns/system) | Noun | A System is the headless software for one job, such as CRM or billing, that every Startup runs on shared data. | | [Team](/business/nouns/team) | Noun | A Team is a named group of Roles under one owner; every Startup starts with eleven default Teams. | | [Variant](/business/nouns/variant) | Noun | A Variant is one value an Experiment can assign, such as a revision, a Price on a sibling Offer, or a prompt, with its lineage. | | [Worker](/business/nouns/worker) | Noun | A Worker is a Human or an Agent that fills a Role and acts on Tasks. | | [Idea.pursue](/business/nouns/idea/pursue) | Verb | Pursue starts a Startup on an Idea as one variant of the Experiment that tests the Idea. | | [Play.apply](/business/nouns/play/apply) | Verb | Apply runs a Play across a Portfolio cohort, one wave at a time, measured as an Experiment. | | [Startup.advance](/business/nouns/startup/advance) | Verb | Advance moves a Startup to its next Lifecycle state once every entry check of that state passes. | | [Startup.build](/business/nouns/startup/build) | Verb | Build provisions the Systems, Sites and Interfaces a Startup’s definition declares, and moves the Startup to Building. | | [Startup.claim](/business/nouns/startup/claim) | Verb | Claim binds a provisional Startup to a verified owner, which enables payments and every Verb that moves money. | | [Startup.clone](/business/nouns/startup/clone) | Verb | Clone copies a Startup’s definition into a new Startup once, with no link back to the source. | | [Startup.graduate](/business/nouns/startup/graduate) | Verb | Graduate moves a Startup to a Company of its own, with its Customers, Domains and records intact. | | [Startup.hold](/business/nouns/startup/hold) | Verb | Hold keeps a Startup running in its current Lifecycle state with no new investment from the Studio. | | [Startup.import](/business/nouns/startup/import) | Verb | Import builds a new Startup from an existing business’s definition: its Offers, Pages, Nouns and Processes. | | [Startup.launch](/business/nouns/startup/launch) | Verb | Launch puts a Startup live on its domain, serving its Offers to Customers. | | [Startup.pause](/business/nouns/startup/pause) | Verb | Pause moves a Startup to Dormant: its scheduled Workflows stop, and its Sites and records stay in place. | | [Startup.resume](/business/nouns/startup/resume) | Verb | Resume returns a Dormant Startup to the Lifecycle state it held when it paused. | | [Startup.sell](/business/nouns/startup/sell) | Verb | Sell transfers a Startup, with its Customers, Domains and records, to a buyer under a signed Agreement. | | [StartupTemplate.extend](/business/nouns/startup-template/extend) | Verb | Extend adds a Startup Template to a Startup’s bases, pinned to a Version, so the Startup inherits its definition. | | [StartupTemplate.promote](/business/nouns/startup-template/promote) | Verb | Promote moves one Startup’s refinement into a Startup Template, so every Startup that extends it inherits the refinement. | | [StartupTemplate.upgrade](/business/nouns/startup-template/upgrade) | Verb | Upgrade moves a Startup to a newer Version of a Startup Template it extends, through a Change it can review. | | [Template.extend](/business/nouns/template/extend) | Verb | Extend adds a Template to a Startup’s bases, pinned to a Version, so the Startup inherits its definition. | | [Template.promote](/business/nouns/template/promote) | Verb | Promote moves one Startup’s refinement into a Template, so every Startup that extends the Template inherits it. | | [Template.upgrade](/business/nouns/template/upgrade) | Verb | Upgrade moves a Startup to a newer Version of a Template it extends, through a Change it can review. | # Markets URL: /code/builders/startup/markets · Id: `page:code/builders/startup/markets` > How a Startup crosses a border into a new Market, with Prices in its currency, a Site in its languages, and the law that wakes there. A [Market](/business/nouns/market) is a region where a [Startup](/business/nouns/startup) sells, hires, or keeps books. Each one sets a currency, a list of locales, and the legal floor rows that wake when the Startup enters it. ## What a Market sets Every Startup starts in the United States Market. The others are opened one at a time. | Market | Currency | Locales | Floor rows it wakes | | --- | --- | --- | --- | | United States | `USD` | `en-US`, `es-US` | [CAN-SPAM](/systems/legal-and-corporate/floor/can-spam), [Phone](/systems/legal-and-corporate/floor/phone), [Sales tax](/systems/legal-and-corporate/floor/nexus), [Privacy rights](/systems/legal-and-corporate/floor/privacy), [Data broker](/systems/legal-and-corporate/floor/data-broker), [Information returns](/systems/legal-and-corporate/floor/information-returns) | | European Union | `EUR` | `en-IE`, `de-DE`, `fr-FR`, `es-ES`, `it-IT`, `nl-NL`, `pl-PL`, `pt-PT`, `sv-SE` | [VAT](/systems/legal-and-corporate/floor/vat), [Jurisdictions](/systems/legal-and-corporate/floor/jurisdictions), [Privacy rights](/systems/legal-and-corporate/floor/privacy), [Accessibility](/systems/legal-and-corporate/floor/accessibility), [Vulnerability handling](/systems/legal-and-corporate/floor/vulnerability-handling), [Whistleblowing](/systems/legal-and-corporate/floor/whistleblowing) | | United Kingdom | `GBP` | `en-GB` | [VAT](/systems/legal-and-corporate/floor/vat), [Jurisdictions](/systems/legal-and-corporate/floor/jurisdictions), [Privacy rights](/systems/legal-and-corporate/floor/privacy) | | Canada | `CAD` | `en-CA`, `fr-CA` | [VAT](/systems/legal-and-corporate/floor/vat), [Jurisdictions](/systems/legal-and-corporate/floor/jurisdictions), [Privacy rights](/systems/legal-and-corporate/floor/privacy), [French language](/systems/legal-and-corporate/floor/french-language) | | Australia | `AUD` | `en-AU` | [VAT](/systems/legal-and-corporate/floor/vat), [Jurisdictions](/systems/legal-and-corporate/floor/jurisdictions), [Privacy rights](/systems/legal-and-corporate/floor/privacy) | A Market names its countries by code, its currency by ISO 4217 code, and its locales by BCP 47 tag with the default first. ## Entering a Market [enter](/business/nouns/market/enter) opens a Market to a Startup in one [Action](/business/nouns/action). The [Finance Lead](/agents/finance/finance-lead) performs it, and because it commits money and law, it is one-way and waits its [delay window](/agents/autonomy-levels/delay-windows). When the window closes, three things happen at once: 1. Every [Price](/business/nouns/price) gains an amount in the Market's currency. 2. The [Site](/business/nouns/site), docs, and [Messages](/business/nouns/message) gain the Market's locales. 3. Every floor row the Market lists wakes and opens its [Process](/business/nouns/process). Take a scheduling API for dental clinics that enters Canada. Its $49 [Offer](/business/nouns/offer) gains a CAD Price and its Site gains `en-CA` and `fr-CA`. The [Company](/business/nouns/company) registers for sales tax there, and the [French language](/systems/legal-and-corporate/floor/french-language) row wakes. ## Currencies A Price shows in the buyer's Market currency, and a [Customer](/business/nouns/customer) pays in that currency. The books record each charge in its own currency and in the Company's home currency at the rate on the day it settles. Payouts settle in the home currency. A Price is set per Market, never converted on the fly. Within one Market, an Offer has one Price for every buyer. A price test runs across Markets as a geo [Experiment](/business/nouns/experiment), never as a split inside one. ## Languages [Localization](/systems/marketing/localization) translates the Site, docs, Messages, and support into each locale. The [Content Lead](/agents/marketing/content-lead) owns it. Every translation records the source [Version](/business/nouns/version) it came from, and a source [Change](/business/nouns/change) retranslates every locale before it ships. Support answers in the Customer's locale. Legal paper is translated by a credentialed [Human](/business/nouns/human) translator, because a contract binds in the language it is signed in. ## Law, tax, and export A Market wakes the floor rows its law adds: [VAT](/systems/legal-and-corporate/floor/vat) and its equivalents, [privacy](/systems/legal-and-corporate/floor/privacy), [accessibility](/systems/legal-and-corporate/floor/accessibility), and its sending rules. Two rows apply at every border. [Sanctions](/systems/legal-and-corporate/floor/sanctions) screens every checkout and every payout against the sanctions lists. [Export controls](/systems/legal-and-corporate/floor/export-controls) classifies [Software](/business/nouns/software) with encryption before its first sale abroad and refuses delivery to embargoed destinations. ## Hiring abroad A Market is also where a Startup hires. A Human who lives there works through an employer-of-record upstream under local law and local payroll, while the Startup seats them in its [Role](/business/nouns/role). [Human workforce](/systems/people/workforce) covers who employs them and how they are paid. ## Next - [Localization](/systems/marketing/localization): how every translation stays in step with its source. - [Legal floor](/systems/legal-and-corporate/floor): every row a Market can wake. - [Offers and pricing](/products/selling/offers-and-pricing): how Prices are set and tested. # Positioning and competitors URL: /code/builders/startup/positioning · Id: `page:code/builders/startup/positioning` > How a Startup's positioning compiles from its Founding Hypothesis, how it tracks competitors, and how every comparison it publishes stays provable. Positioning is where a [Startup](/business/nouns/startup) stands against what its [ICP](/business/nouns/icp) uses today. It compiles from the Founding [Hypothesis](/business/nouns/hypothesis), so every [Page](/business/nouns/page), [Ad](/business/nouns/ad), and opening line says the same thing. ## Six parts, one source Positioning is never a separate document. Each part reads from a slot or a record the Startup already keeps. | Part | Answers | Read from | | --- | --- | --- | | Alternative | What the ICP hires today | The switch slot: the [Organization](/business/nouns/organization), spreadsheet, or person they would leave | | Differentiation | Where the Startup wins | The differentiation slot: two axes, each measured by a [Metric](/business/nouns/metric) | | Value | What winning is worth | The [Problem](/business/nouns/problem)'s current cost, in time or money | | [Customer](/business/nouns/customer) | Who cares most | The customer slot: the ICP | | Category | Where a buyer looks for it | The [Story](/business/nouns/story)'s category | | One-liner | All of it in one sentence | The Story's one-liner | The [Marketing Lead](/agents/marketing/marketing-lead) writes the positioning from those parts, and the [Founder](/agents/founding/founder) makes the calls. Every Page and Ad records the slot and version it came from. ## Competitors A competitor is a company that sells to the same Customers. The Startup records each one as an Organization it competes with. The relationship runs one way: a competitor need not track the Startup back. The switch slot names the strongest alternative, and it is often not a rival product. A spreadsheet, a bookkeeper, or doing nothing beats most new Startups, so the alternative leads and named rivals follow. [Market data](/systems/marketing/market-data) watches each competitor from the outside: search rankings, answer citations, the ads it runs, and its social reach, each with provenance. [Strategy](/workflows/processes/strategy) reads those readings beside the Startup's own [Evidence](/business/nouns/evidence) and keeps the positioning true to both. ## The differentiation 2x2 The differentiation slot's two axes form a 2x2. The Startup and each competitor take a placement on it, and each placement cites its Evidence. The axes are chosen so the Startup sits alone in one corner. The stronger axis is one a competitor cannot buy, such as an [Audience](/business/nouns/audience) the Startup owns. Data that compounds with each Customer is another, and so is a low cost that the [Portfolio](/business/nouns/portfolio)'s shared [Systems](/business/nouns/system) make possible. ## Proof, not adjectives Each differentiation axis shows the strongest grade of its outside Evidence, as every slot does. An axis graded Opinion is a guess, and the [weekly test](/code/builders/startup/experimentation) ranks it for testing first. A comparison published on a Page names a competitor only truthfully. [Comparative advertising](/systems/legal-and-corporate/floor/comparative-advertising) requires every comparative claim to be substantiated before it runs. A competitor that disputes a claim writes to the [legal notices](/systems/trust-and-governance/intakes) intake. ## When positioning changes The differentiation slot changes through an [Experiment](/business/nouns/experiment). A fake door tests a new axis on the live [Site](/business/nouns/site) before anything is built, and the winning [Variant](/business/nouns/variant) becomes the slot. A changed slot is a new Founding Hypothesis version. Site copy, [Offers](/business/nouns/offer), and [Plays](/business/nouns/play) built on it recompile, and the diff is previewed as a [Change](/business/nouns/change) before it lands. On a Live Startup, a new version is a [pivot](/business/nouns/startup/pivot), recorded as a [Decision](/business/nouns/decision). ## Example platecost.app names the spreadsheet and the bookkeeper as the alternative, and two restaurant back-office suites as rivals. Its axes are speed (margins the same day) and grain (cost per plate), worth four owner hours a week. Its one-liner reads: "plate costs that update the day the invoice arrives." ## Next - [Customers and hypothesis](/business/record/customers-and-hypothesis): the five slots positioning reads from. - [Marketing playbook](/workflows/marketing/playbook): how positioning drives every Page and Play. - [Experimentation](/code/builders/startup/experimentation): how a slot is tested. # Principles URL: /code/builders/startup/principles · Id: `page:code/builders/startup/principles` > Seven rules every Startup on StartupBuilder follows, from the definition that runs to the honesty it cannot opt out of. Seven rules hold for every [Startup](/business/nouns/startup) that [StartupBuilder](/code/builders/startup) runs. Each one is enforced by the platform, not left to the judgment of whoever runs the Startup. ## The definition is the business What the definition says is what the Startup does. No side process runs outside it, no price lives in a spreadsheet, and no [Role](/business/nouns/role) exists only in someone's head. A newcomer, human or [Agent](/business/nouns/agent), learns the business by reading its definition. A founder who wants the business to behave differently edits the definition through a [Change](/business/nouns/change), and the running Startup follows. ## Types are discipline A typed record cannot be vague. A [Hypothesis](/business/nouns/hypothesis) must name the [Metric](/business/nouns/metric) and threshold that settle it, so "teachers love it" never passes as a test. ```ts import { $ } from 'startup-builder' await $.Hypothesis.create({ statement: 'Roofers pay two cents a record for verified permits', kind: 'loop', metric: 'paidLookupsPerWeek', threshold: '10000 within four weeks', }) ``` An empty field is dropped or filled with a sourced value, never guessed. Structural facts, such as which acts need a license in a state, come from published registries and standards, not from a model. ## Goals are tests A [Goal](/business/nouns/goal) is a set of assertions the platform checks continuously, not a slide. Each [Key Result](/business/nouns/key-result) names a Metric, a baseline, a target, and a deadline, and reads its value from [Events](/business/nouns/event). ```ts await $.Goal.create({ objective: 'Teachers rebook without being asked', horizon: 'quarter' }) await $.KeyResult.create({ baseline: 0.35, target: 0.6, deadline: '2026-12-31' }) // reads rebookingRate ``` A Key Result off its line raises a [Decision](/business/nouns/decision) for the Role that owns the work. No [Team](/business/nouns/team) owns a Metric; the [Processes](/business/nouns/process) that move it do. ## Work goes to the cheapest capable worker Every step runs as code, a generative model, an Agent, or a [Human](/business/nouns/human), in that order of preference. A miss or low confidence escalates one rung, and the caller never sees which kind did the work. The performer is never the checker. An [Evaluator](/business/nouns/evaluator) grading an Agent runs on a different model from the Agent, and nobody approves their own Change. ## Autonomy is earned; oversight is declared Autonomy grows with evidence. An Agent moves up a rung when its verdicts agree with review 95 percent of the time. It drops a rung on a regression, with no ticket filed. Oversight does not move with capability: it is declared per step for a lasting reason, such as regulation, stakes, or harm to consumers. A tax filing waits for a credentialed preparer however good the model becomes. A refund over its [Limit](/business/nouns/limit) waits for whoever holds that Limit. ## Every change is an experiment Any Change to an [Offer](/business/nouns/offer), [Price](/business/nouns/price), [Page](/business/nouns/page), message, or [Play](/business/nouns/play) can run as variants against a Hypothesis. The winner becomes the definition, and the losing variant concludes with its [Evidence](/business/nouns/evidence). Nothing is deleted. A concluded variant keeps its record, and a Startup with no signal goes Dormant and can return. Across a [Portfolio](/business/nouns/portfolio), winners flow into [Startup Template](/business/nouns/startup-template) defaults, so each new Startup inherits the best version known and the business compounds. ## Honest by construction A Startup cannot ship a fabricated [Customer](/business/nouns/customer), an invented Metric, a fake badge, a placeholder feature, or staff who do not exist. Social proof on its [Site](/business/nouns/site) renders from payments and usage; with none, the section does not render. Before a Startup is Live, proof is a target, not a claim. The lesson-booking Startup's Site says it is taking its first 50 teachers, and it shows a teacher count only once teachers have paid. ## Next [Vision](/code/builders/startup/vision) explains why StartupBuilder runs a business as a program. # Promise ledger URL: /code/builders/startup/promise-ledger · Id: `page:code/builders/startup/promise-ledger` > Launch readiness is a number, counted by binding every promise in the docs to a registry id the platform runs. Launch readiness is a number: how many of the promises in these docs bind to something the platform runs. The promise ledger counts it on every page, and the build fails on a promise that binds nothing. ## What counts as a promise A promise is a sentence that says the platform does something. The verifier reads three kinds on every hand-written page. - Each row of a contract table. - Each row of a hand-written [Verbs](/business/nouns/verb) table. - Each line that says what a [System](/business/nouns/system) does. Generated sections are not counted. The registry wrote them, so they bind by construction. ## How a promise binds A promise binds to the registry ids it links or names in code. Linking a Verb, an [Event](/business/nouns/event), a property, a [Workflow](/business/nouns/workflow), a [Metric](/business/nouns/metric), a [Control](/business/nouns/control) or an error types it. | Grade | The promise | | --- | --- | | `proven` | Binds a Verb whose conformance test passes in the test environment. | | `typed` | Binds a Verb, Event, property, Workflow, Metric, Control or error. | | `named` | Links only [Nouns](/business/nouns/noun): the record exists, but nothing says what runs. | | `unbound` | Binds nothing. | A promise can name `Noun.verb` in code when the registry holds no such Verb, Event or property. That promise is unresolved, and it fails the way an unbound one does. ## The number Every System and capability page prints its count, such as 14 of 16 promises typed. A coverage page ranks Systems by unbound promises, so the next piece of work is always the top row. Each System also declares its category leader's job list. Parity is the share of those jobs whose Verbs all resolve: a System covering 18 of 20 jobs scores 0.9. For a [Startup Template](/business/nouns/startup-template), readiness is a typed path from [Idea](/business/nouns/idea) to a closed month, walked every night by the [Founder Run](/code/founder-run). ## The money spine first The first rows to turn green are the ones every [Startup](/business/nouns/startup) crosses on its way to cash. That is the revenue chain, [Prospect](/business/nouns/prospect) to [Lead](/business/nouns/lead) to [Deal](/business/nouns/deal) to [Quote](/business/nouns/quote) to [Order](/business/nouns/order) or [Subscription](/business/nouns/subscription) to [Renewal](/business/nouns/renewal), with its [Acquisition](/business/nouns/acquisition) carried down each step. Every Verb that moves money also declares the ledger [Entries](/business/nouns/entry) it writes. The verifier fails a money Verb with no posting rule, so the books compile from the grammar. ## Example A [Billing](/systems/billing) page promises that it refunds through `Order.refund` and that it recovers failed payments. The first binds `verb:Order.refund` and grades `typed`; the second binds nothing and fails the build at its line. Linking the [Dunning](/workflows/processes/billing/dunning) Workflow that keeps it turns the row `typed`. # Publication boundary URL: /code/builders/startup/publication-boundary · Id: `page:code/builders/startup/publication-boundary` > A Startup's Customers meet its Publication, a branded package of addresses, packages, keys and docs, and never the platform. A [Startup](/business/nouns/startup)'s [Customers](/business/nouns/customer) meet its [Publication](/business/nouns/publication), never the platform. Every address, package, key, header and error a Customer sees carries the Startup's own [Brand](/business/nouns/brand). ## What a Publication holds One record holds everything a Customer touches, all on the Startup's [Domain](/business/nouns/domain). | What | Property | For openhours.dev | | --- | --- | --- | | API | `api` | `https://openhours.dev/api` | | MCP server | `mcp` | `https://openhours.dev/mcp` | | Docs, with `llms.txt` | `docs` | `https://openhours.dev/docs` | | Status page | `statusPage` | `https://openhours.dev/status` | | [Portal](/business/nouns/portal) | `portal` | `https://openhours.dev/portal` | | SDK, CLI and MCP packages | `packages` | `openhours` in each package registry | | API key prefix | `keyPrefix` | `openhours_sk_live_` | | Key variable | `keyEnv` | `OPENHOURS_API_KEY` | | Webhook signature header | `webhookHeader` | `Openhours-Signature` | | Error namespace | `errorNamespace` | `https://openhours.dev/errors` | ## How it compiles A Publication compiles from the Brand and one [Version](/business/nouns/version). [Deploying](/business/nouns/version/deploy) a Version compiles a new Publication. A restyle compiles one too and leaves the API version alone. Everything a Customer uses compiles into it: the buy links the [publish gate](/code/builders/startup/publish-gate) emits, the [Components](/business/nouns/component) a Customer embeds, and the generated docs. ## The boundary Nothing inside a Publication names the platform: no [api.sb](/code/platform/api-sb) address, no `STARTUP_BUILDER_` variable, no `startup-builder` package. The verifier fails any page written for a Startup's Customers that shows one. The Startup's own [Workers](/business/nouns/worker) still call api.sb with the platform SDK. Only the Customer's side differs. ## Self-host [StartupBuilder](/code/builders/startup) is the [Studio](/business/nouns/studio)'s own Publication. Every tool a founder gets here, from keys and logs to usage and the test environment, exists in every Startup's Publication for its own Customers. # The publish gate URL: /code/builders/startup/publish-gate · Id: `page:code/builders/startup/publish-gate` > Publishing an Offer emits every way to buy it, computes tax, and refuses an Offer that loses money on its median Customer. [`Offer.publish`](/business/nouns/offer/publish) is where a [Startup](/business/nouns/startup)'s business compiles. One call emits every way to buy on the Startup's [Publication](/business/nouns/publication), computes tax, and refuses an [Offer](/business/nouns/offer) that loses money on its median [Customer](/business/nouns/customer). ## What it emits | Buy link | Who buys through it | | --- | --- | | Hosted checkout | A person paying by card, on the Startup's [Domain](/business/nouns/domain). | | Payment link | A [Lead](/business/nouns/lead) who said yes: one link takes the money. | | Pricing table component | A [Visitor](/business/nouns/visitor) on the Startup's [Sites](/business/nouns/site) and [Apps](/business/nouns/app). | | [Portal](/business/nouns/portal) entry | A Customer changing or canceling a [Subscription](/business/nouns/subscription). | | MCP `buy` tool | An [Agent](/business/nouns/agent) buying from a chat or coding tool. | | HTTP 402 endpoint | An Agent that pays per call. | `prices.json`, linked from `agents.json`, lists every Offer, [Price](/business/nouns/price) and [Meter](/business/nouns/meter) for Agents that read before they buy. Stripe is the rail. Each charge runs through the Startup's own Stripe account, and Stripe Tax computes tax on every [Order](/business/nouns/order), because the Startup is the seller of record. ## The contribution floor Before it writes, `Offer.publish` runs one [Guard](/business/nouns/guard). The Guard reads the [Cost](/business/nouns/cost) per [Verb](/business/nouns/verb) of each [Entitlement](/business/nouns/entitlement) the Offer grants. It starts from the [Portfolio](/business/nouns/portfolio)'s prior and shrinks toward the Startup's own readings as they arrive. The floor is the lowest Price that keeps the Startup's target margin: Cost ÷ (1 − target margin). - When the median Customer falls below the floor, the call is refused with [`below-contribution-floor`](/code/api/errors/below-contribution-floor), which names the floor Price. - When the median clears it and the 95th-percentile Customer does not, the Offer publishes with a usage [Limit](/business/nouns/limit) at break-even. The Offer's `atBound` behavior applies there. ## Example A $29 monthly Offer transcribes audio at $0.02 a minute; its median Customer uses 450 minutes ($9) and its 95th-percentile Customer 2,050 ($41). At a 60% target margin the floor is $9 ÷ 0.4 = $22.50, so the Offer publishes. The heavy Customer outspends the Price, so the Offer gains a Limit of 1,450 minutes, where Cost meets $29. # Synthetic walkers URL: /code/builders/startup/synthetic-walkers · Id: `page:code/builders/startup/synthetic-walkers` > Synthetic founders and buyers walk every Startup Template through the published Interfaces and file each step that stops. Synthetic [Agents](/business/nouns/agent) walk every path a person walks, before a person does. The [Founder Run](/code/founder-run) drives a founder and a set of buyers through the published [Interfaces](/business/nouns/interface) alone, and records every step that stops. ## Two roles Every night, a synthetic [Founder](/agents/founding/founder) starts from each [Startup Template](/business/nouns/startup-template), under each operating model and [Motion](/business/nouns/motion). It drives the [Startup](/business/nouns/startup) from [Idea](/business/nouns/idea) to a closed month, which measures how complete the platform is. On every deploy, buyer Agents drawn from the Startup's [ICP](/business/nouns/icp) sign up, pay with a test card, ask, cancel and dispute against one [Version](/business/nouns/version). A regressed verdict refuses [`Version.deploy`](/business/nouns/version/deploy). ## Checkpoints | Checkpoint | Reached by | | --- | --- | | Idea | `Idea.create` | | Founding [Hypothesis](/business/nouns/hypothesis) | `Hypothesis.create` | | Live in the test environment | `Startup.launch` | | First paid [Order](/business/nouns/order) | `Order.pay` | | First [Customer](/business/nouns/customer) [Conversation](/business/nouns/conversation) | `Conversation.create` | | Month-end close | `Period.close` | | The week's test [Decision](/business/nouns/decision) | `Decision.create` | A step fails in three cases. It needs a [Verb](/business/nouns/verb) no Interface exposes, a page names a record the API cannot return, or it needs a person outside the legal floor. Each failure opens an [Issue](/business/nouns/issue) that quotes the transcript line. The run's clock is bound to a Stripe test clock. [Renewals](/business/nouns/renewal), dunning, trials and delay windows fire in minutes, not months. ## The published surface only Walkers read what any coding Agent reads: the Markdown twin of each page, `llms.txt`, the OpenAPI document and the MCP tools. A gap between two Interfaces, such as a quote step a [Service](/business/nouns/service) never exposes, shows on the first night. ## The number The headline is how many of the 9 Startup Templates have a typed path to a closed month. A checkpoint whose Verb the registry lacks goes to the top of the [promise ledger](/code/builders/startup/promise-ledger). A Startup Template that fails stays off the catalog until it passes. ## Example The founder marketplace walker reaches its first paid Order in 11 minutes, then stops at its first Customer Conversation: no MCP tool reaches a seller. An Issue opens with the transcript line, and the Startup Template leaves the catalog until a [Change](/business/nouns/change) fixes it. # Test and live URL: /code/builders/startup/test-and-live · Id: `page:code/builders/startup/test-and-live` > Every Startup runs in a test environment and a live one over one definition, and proves every Offer in test before launch. Every [Startup](/business/nouns/startup) runs in two environments over one definition: `test`, where nothing real happens, and `live`, where [Customers](/business/nouns/customer) pay. A Startup proves every [Offer](/business/nouns/offer) in `test` before [launch](/business/nouns/startup/launch) opens `live`. ## One definition, two sets of records Both environments share the definition: [Nouns](/business/nouns/noun), [Verbs](/business/nouns/verb), Offers, [Pages](/business/nouns/page), [Workflows](/business/nouns/workflow) and [Roles](/business/nouns/role). Every operational record, such as an [Order](/business/nouns/order), a [Message](/business/nouns/message) or a [Cost](/business/nouns/cost), belongs to exactly one environment and never crosses to the other. `test` runs the latest merged [Change](/business/nouns/change); `live` runs the [Version](/business/nouns/version) last deployed. An edit is callable in `test` at once, while Customers in `live` keep the deployed build. The key picks the environment: an `sk_test_` key reaches `test`, and an `sk_live_` key reaches `live`, at the same URL. [Environments](/code/cli/guides/environments) covers the developer contract. ## What test simulates `test` runs every Verb for real, except the effects that reach the outside world. | In `test` | What happens instead | | --- | --- | | Payments | Test cards charge in Stripe's test environment, and no money moves | | Outbound messages | Reach only seed inboxes and the Startup's own team | | Outside effects | [Domain](/business/nouns/domain) purchases, ad spend and filings run against simulators and record as `done` | | [Human](/business/nouns/human) steps | Route to the owner, who signs as the test signer | | [Agents](/business/nouns/agent) | Run for real, with real model calls | Everything else matches `live`: [Permissions](/business/nouns/permission), [Limits](/business/nouns/limit), [Approvals](/business/nouns/approval), delay windows and [Events](/business/nouns/event). A refund over its Limit waits for an Approval in `test` exactly as it would in `live`. A run in which Agents only pretend proves nothing. Model calls are real, so the test run exercises the same judgment Customers meet in `live`. ## The test run that admits Live Test run passed is a [Live](/business/lifecycle/states/live) entry check. A sample Customer for each [Persona](/business/nouns/persona) completes every published Offer end to end. It finds the Offer, pays with a test card, receives the work, and confirms it. Take a Startup that sells monthly accessibility audits of online stores. Its sample store owner signs up, pays $199 with a test card, and receives an audit of a seeded storefront. A second run disputes one finding, to prove the remedy works too. The check holds only for the Version it ran against. A Change merged after the run makes it stale, and the run repeats before launch. ## Launch opens live Launch waits for every Live entry check, then deploys the current Version to `live` and puts the Startup on its Domain. Before the first launch, every call with a live key returns [`not-live`](/code/api/errors/not-live). Records never move. Customers and Orders from `test` stay in `test`, and `live` starts empty. From then on, `live` runs only what was deployed, and the previous Version stays one [revert](/business/nouns/change/revert) away. ## Numbers never mix Every [Metric](/business/nouns/metric) counts `live` records only, and every figure from `test` carries a test label. A test Customer is never outside, so no test Order moves a Startup toward [Repeatable](/business/lifecycle/states/repeatable). Resetting `test` data never touches `live`. A founder can wipe `test` and rehearse a launch as often as they like. ## Agents build, humans claim An Agent can create a Startup, build it, and sell to test Customers with no human present. Every provisional Startup holds a no-money Limit until a verified owner takes responsibility for it. A human sponsor [claims](/business/nouns/startup/claim) the Startup through one link, which opens its payment account and lifts that Limit. The Agent then launches, and the sponsor is the owner of record. [Sponsor an agent](/agents/sponsor) walks through the claim. ## Next [Build and publish](/workflows/lifecycle/build-and-publish) lists the full launch checklist, and the [Lifecycle](/business/nouns/lifecycle) shows what happens after Live. # Vision URL: /code/builders/startup/vision · Id: `page:code/builders/startup/vision` > StartupBuilder treats a business as a program, with a definition that runs, a market that scores it, and a loop that improves it every week. [StartupBuilder](/code/builders/startup) treats a business as a program. A [Startup](/business/nouns/startup) is one definition that runs, a market scores it, and every week it ships a better version of itself. ## A business is a program Models became superhuman at math and code first, because both have four things: a formal representation, execution, a reward signal, and fast iteration. A business had none of them: its rules lived in heads, its work in inboxes, its score in a quarterly spreadsheet. StartupBuilder gives a business all four. The definition is the formal representation: [Nouns](/business/nouns/noun), [Verbs](/business/nouns/verb), [Products](/business/nouns/product), [Offers](/business/nouns/offer), [Roles](/business/nouns/role), and [Goals](/business/nouns/goal), typed and versioned. [api.sb](/code/platform/api-sb) executes it. Revenue and [Metrics](/business/nouns/metric) are the reward, and the market computes them, not a judge. Iteration is the fourth. Every edit is a [Change](/business/nouns/change), and any Change can run as an [Experiment](/business/nouns/experiment) against a [Hypothesis](/business/nouns/hypothesis). A Startup that tests one Change a week runs 52 experiments a year on its own business. ## The definition is the business One shared runtime reads every Startup's definition and runs it. No Startup owns a codebase to maintain, so no Startup drifts from what it says it is. Take a Startup that sells verified building-permit data to roofing contractors. Its definition names a `Permit` Noun, a `Permit.verify` Verb, a usage Offer at two cents a record, and a Goal of 300 paying contractors. Raising the price is one Change. The pricing [Page](/business/nouns/page), the API response, and the next [Invoice](/business/nouns/invoice) all read the new [Price](/business/nouns/price) from the same record. The operations manual and the operation are one record, so the manual cannot go stale. An [Agent](/business/nouns/agent) reading the definition sees what the business does, because the definition is what the business does. ## Start from demand A Startup starts from a [Problem](/business/nouns/problem) that a reachable buyer pays to solve. The Problem and the outcome the Startup sells describe one state of the world with opposite signs. The demand it chases and the Offer it sells share one structure. The founding Hypothesis is the root record. It names who the buyer is, what hurts, what the Startup offers, how it differs, and why now. [Site](/business/nouns/site) copy, Offers, Prices, and [Plays](/business/nouns/play) compile from it, each traced to the slot it came from. Each slot shows its strongest [Evidence](/business/nouns/evidence): behavior beats commitment, and commitment beats opinion. The first test is a reserve page. Buyers place a refundable deposit before the Product exists, and the deposits grade the Hypothesis in days. ## Systems, Agents, and Processes Every Startup splits its work three ways. [Systems](/business/nouns/system) hold durable state and run deterministic operations, with no judgment, and Agents judge at named decision points and act only through Systems. [Processes](/business/nouns/process) sequence System operations and Agent judgments toward a verifiable outcome, and hold neither state nor judgment. The boundaries are tests. Judgment inside a System is a misplaced Agent, and a Process step that keeps state is a hidden System. Because Agents propose and Processes commit through Systems after a check passes, the performer is never the checker. ## Autonomy grows, oversight stays put An Agent fills every Role by default. A [Human](/business/nouns/human) joins a Role by choice, signs where the law reserves an act to a person, and decides where an [Action](/business/nouns/action) exceeds a [Limit](/business/nouns/limit). No human sits in a path because a model falls short. Autonomy tracks what models can do and rises with each release, with no rebuild. Oversight is declared per step for a reason that does not change with capability: regulation, stakes, consumer harm. A Startup that caps refunds at $500 sends every larger refund to a person, whatever the model scores. Restraint counts as a move. Waiting for Evidence, holding cash, or pausing a failing Play is a [Decision](/business/nouns/decision), recorded with its options, its choice, and its reason. ## Variation, not validation Creating a Startup costs close to nothing, so the riskiest assumption becomes an axis of variants that the market grades. Three Startups can test one [Idea](/business/nouns/idea) on three buyers in the same week. Nothing is deleted: a Startup with no signal goes Dormant and keeps its records, Site, and domain. A [Studio](/business/nouns/studio) runs StartupBuilder across a [Portfolio](/business/nouns/portfolio). Startups are variants of Ideas and [Startup Templates](/business/nouns/startup-template), and Plays roll out by [Cohort](/business/nouns/cohort) with control arms. Winning variants flow back into Startup Template defaults, so each new Startup starts from the best version known. The bar is not a first dollar. It is profit, across many Startups, at a quality a buyer trusts. ## Next [The Startup as code](/code/builders/startup/business-as-code) describes the model every definition is written in. # Wants URL: /code/builders/startup/wants · Id: `page:code/builders/startup/wants` > Unmet demand sensed across every Startup becomes graded Evidence on a Problem, and a refundable deposit proves it before anything is built. When building costs almost nothing, the scarce thing is demand. [StartupBuilder](/code/builders/startup) records every unmet want as graded [Evidence](/business/nouns/evidence) on a [Problem](/business/nouns/problem), and asks for a refundable deposit before anything is built. ## Where wants come from A want is never typed in. It is written when someone acts on a need that no [Offer](/business/nouns/offer) meets, and each source writes Evidence at the grade its act deserves. | Where | What happened | Grade | | --- | --- | --- | | [Agent](/business/nouns/agent) request | a buying agent asks for an Offer and nothing matches | behavior | | Empty search | a [Visitor](/business/nouns/visitor) searches a [Site](/business/nouns/site) and finds nothing | behavior | | Uncovered request | a [Customer](/business/nouns/customer) asks support for something no Offer covers | behavior | | Refused [Order](/business/nouns/order) | an Order fails because no Offer can fill it | behavior | | [Waitlist](/business/nouns/waitlist) join | a Visitor joins the line for an Offer that is not open | behavior | | [Interview](/business/nouns/interview) answer | an [ICP](/business/nouns/icp) member describes the last time the Problem cost them | behavior | | Deposit | a buyer pays a refundable deposit on a reserve Offer | commitment | | Stated wish | someone says they would use it | opinion | Opinion stays on the record and weighs zero. Frequency, urgency, and willingness to pay are computed from the Evidence, never entered as fields. ## The want ledger The want ledger is one read across every [Startup](/business/nouns/startup) in the [Portfolio](/business/nouns/portfolio). It ranks Problems by the outside Evidence behind them and shows the distinct ICP members who asked. It is a [Dashboard](/business/nouns/dashboard) over the kept record, not a separate store. A Problem that 40 people hit this month, with three deposits, outranks one with 400 opinions. The [Studio](/business/nouns/studio) drafts new Startups from the top of the ledger, so their first buyers exist before their first [Page](/business/nouns/page). When such a Startup goes Live, everyone who asked and agreed to hear back is told first. A Dormant Startup stays subscribed to its Problem and wakes when commitment-grade Evidence returns. One Startup's Customers never become another Startup's prospects by default. Wants cross between Startups as counts per Problem, and a person's identity crosses only with their [Consent](/business/nouns/consent). ## Reserve-first Reserve-first is a new Startup's first test: a reserve page, published on day one, that takes a refundable deposit on the real Offer. The page states the Problem in the ICP's own words, the approach, the [Price](/business/nouns/price), and a deliver-by date. A deposit is an authorization against that Price. If the Startup misses its date, every deposit refunds automatically, so the buyer risks nothing but attention. Deposits are commitment-grade Evidence, the strongest grade a Startup can collect before it has a [Product](/business/nouns/product). Saying yes is free; paying is not. A meal-planning app for people with celiac disease posts its reserve page at $9 a month, with a $9 deposit and a 30-day date. A payroll tax-table [Dataset API](/products/templates/dataset-api) for developers posts at $400 a month with a $40 deposit. Within two weeks each knows whether anyone pays. ## What a deposit proves A deposit counts only from an outside buyer: one who shares no owner, Studio account, [Agreement](/business/nouns/agreement), or sibling chain with the Startup. Purchases between sibling Startups are real revenue, reported apart, and never pass a gate. Commitment-grade Evidence from outside ICP members moves a Startup from [Idea](/business/nouns/idea) to [Building](/business/lifecycle/states/building). The Building state's one [Metric](/business/nouns/metric) that matters is [Committed ICP members](/agents/founding#committed-icp-members). Simulated buyers can prune variants before real traffic, and their results are graded opinion. A simulated conversion is a claim about buyers, not a buyer, so it never decides a [Lifecycle](/business/nouns/lifecycle) transition. ## Wants across the Studio Sibling Startups race as variants of one Idea. Each takes a different ICP or approach, opens its own reserve page, and is judged on deposits. The losers go Dormant and keep their Evidence. An audience is a source of wants too. A creator's comments, questions, and complaints read as Evidence on Problems. The Studio drafts two or three Startups for that audience, each with a reserve page, and offers the creator equity for distribution. Every Startup writes to the same record, so each new Startup starts with the demand that every earlier one sensed. ## Next - [Test demand](/workflows/processes/test-demand): the cheapest test that settles each [Hypothesis](/business/nouns/hypothesis). - [Problem interview](/workflows/processes/problem-interview): Evidence from the people who have the Problem. - [Experimentation](/code/builders/startup/experimentation): how every change becomes a test. # create-startups URL: /code/cli/create-startups · Id: `page:code/cli/create-startups` > npm create startups: its inputs, flags, templates, and the records and files it creates. `npm create startups` creates a [Startup](/business/nouns/startup) in [api.sb](/code/platform/api-sb) and a local directory that defines it as code. ### Usage ```bash npm create startups "Acme AI" pnpm create startups acme.com yarn create startups bun create startups npx create-startups --json '{"name":"Acme AI","idea":"Patent drafts for solo inventors"}' ``` ### Inputs | Input | Example | Creates | | --- | --- | --- | | A name | `"Acme AI"` | One Startup on a free subdomain | | A domain | `acme.com` | One Startup on that domain | | Several names | `"Acme AI" "Beta Labs"` | One Startup each | | JSON | `--json '{"ideas":[…]}'` | One Startup per idea | | Nothing | None. | Prompts for an idea, then suggests names | ### Flags | Flag | Value | Description | | --- | --- | --- | | `--template` | `