Calling it four ways
Tutorial 4 of 12 imports Leaseline's rent roll and calls the same lease Verbs through the API, SDK, CLI and MCP.
Every Verb has one name and one JSON input on every Interface. Leaseline declares a Lease Noun, and its records arrive by import, then answer the same call four ways.
What you build
You map a property manager's rent roll into Lease records, then list and renew leases through the API, the SDK, the CLI and MCP. Each call returns one Action.
Steps
To import a rent roll, map its columns onto the Noun:
mappings/rent-roll.ts import { mapping } from 'startup-builder' export default mapping({ from: 'csv', to: 'Lease', fields: { unit: 'Unit', endsOn: (row) => new Date(row['Lease End']).toISOString().slice(0, 10), rent: (row) => ({ amount: Number(row['Monthly Rent']), currency: 'USD' }), }, })To list the leases up for renewal, call the API:
curl "https://api.sb/ leaseline.app/ leases? where= status%20%3D%20renewing" \-H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" To do the same in code, use the SDK:
TypeScript import { $ } from 'startup-builder' const due = await $.Lease.list({ where: 'status = renewing', sort: 'endsOn', limit: 50 })To renew one from a terminal or CI, use the CLI:
npx startup-builder do Lease.renew --json '{"lease":"lease_4loEed1JG4", "months": 12}' To let an agent do it, give it the MCP server. Its
dotool runs the same SDK line as one Action:JSON { "name": "do", "arguments": { "code": "return await $.Lease.renew({ lease:'lease_4loEed1JG4', months: 12 })" } }
Result
The rent roll became Lease records, and one Verb answered four Interfaces with the same name, input and Action. The parity matrix sets every operation side by side. Checkpoint leaseline@ch04 (status planned) adds mappings/.
Next steps
- Tutorial 5 puts a price on it.
- IDs and pagination and filtering: the rules every call follows.