Public: anyone can read this; the crew can change it.
API
What the app describes at /openapi.json, read live.
18 operations in 4 areas
api 14
-
GET /api/audit
Parameters
limit query integer before query integer 200 The audit trail, newest first; `before` pages back by id.
default { error, message }: why not
Fields
error string required message string -
GET /api/audit/{id}
Parameters
id path integer required 200 One row of the audit trail.
Fields
id integer required at string required who_id string | null who_name string | null role enum(anon, user, admin) required resource string required verb string required target string | null allowed enum(0, 1) required outcome string required default { error, message }: why not
Fields
error string required message string -
GET /api/listings
Parameters
limit query integer status query enum(all, active, under_contract, sold, coming_soon, off-market, needs-approval) q query string 200 The listings, newest first, each with how many phrases the Fair Housing check flags. Filter by status and search the address.
default { error, message }: why not
Fields
error string required message string -
POST /api/listings
Body
address string required beds integer required baths number required sqft integer required lot string required year integer required price integer required features string[] required tone enum(classic, warm, bold) palette enum(navy, forest, burgundy, charcoal, teal) agent_name string required brokerage string required license string required agent_phone string required agent_email string required open_houses object[] 201 Launch a listing from its facts and the agent's brand: all five assets, generated and checked. When the signed-in person already launched the same address (any case or spacing) the answer is 409 duplicate_address with the existing id, unless `again: true` is sent.
Fields
id integer required author_id string required author_name string required address string required beds integer required baths number required sqft integer required lot string required year integer required price integer required features string[] required tone enum(classic, warm, bold) required palette enum(navy, forest, burgundy, charcoal, teal) required agent_name string required brokerage string required license string required agent_phone string required agent_email string required open_houses object[] required photos string[] required headshot string | null required status enum(coming_soon, active, under_contract, sold, withdrawn, expired) required sold_price integer | null required was_price integer | null required created_at string required updated_at string required showings object[] assets object[] required default { error, message }: why not
Fields
error string required message string -
GET /api/listings/{id}
Parameters
id path integer required 200 One listing, with its assets and each one's Fair Housing check; for the listing's agent or an admin, also its logged showings, newest first.
Fields
id integer required author_id string required author_name string required address string required beds integer required baths number required sqft integer required lot string required year integer required price integer required features string[] required tone enum(classic, warm, bold) required palette enum(navy, forest, burgundy, charcoal, teal) required agent_name string required brokerage string required license string required agent_phone string required agent_email string required open_houses object[] required photos string[] required headshot string | null required status enum(coming_soon, active, under_contract, sold, withdrawn, expired) required sold_price integer | null required was_price integer | null required created_at string required updated_at string required showings object[] assets object[] required default { error, message }: why not
Fields
error string required message string -
DELETE /api/listings/{id}
Parameters
id path integer required 200 Remove a listing, its assets and its photos.
Fields
id integer required default { error, message }: why not
Fields
error string required message string -
PATCH /api/listings/{id}
Parameters
id path integer required Body
kind enum(mls, social_short, social_medium, social_carousel, social_status, social_price, flyer, email) text string tone enum(classic, warm, bold) status enum(coming_soon, active, under_contract, sold, withdrawn, expired) sold_price integer | null facts object photos object restore integer approved boolean seen string 200 Edit one asset's words, put an earlier version back ({ kind, restore }), withdraw an approval ({ kind, approved: false }; approving is refused, a person does it on the page, and says so with tooLong when a short post is over X's 280 or the MLS description is over its 1,000-character remarks limit), write every asset again in a tone, mark it coming soon, active, under contract, sold, withdrawn or e
Fields
id integer required author_id string required author_name string required address string required beds integer required baths number required sqft integer required lot string required year integer required price integer required features string[] required tone enum(classic, warm, bold) required palette enum(navy, forest, burgundy, charcoal, teal) required agent_name string required brokerage string required license string required agent_phone string required agent_email string required open_houses object[] required photos string[] required headshot string | null required status enum(coming_soon, active, under_contract, sold, withdrawn, expired) required sold_price integer | null required was_price integer | null required created_at string required updated_at string required showings object[] assets object[] required default { error, message }: why not
Fields
error string required message string -
POST /api/listings/{id}/showings
Parameters
id path integer required Body
date string agent string interest enum(not_interested, maybe, interested, offer_likely) required feedback string 201 Log a showing: the day, the buyer's agent, how interested they were and one line of feedback. Only the listing's agent or an admin; a refused field is named in the 422.
Fields
id integer required showing integer required default { error, message }: why not
Fields
error string required message string -
DELETE /api/listings/{id}/showings/{showing}
Parameters
id path integer required showing path integer required 200 Remove a showing the agent logged.
Fields
id integer required default { error, message }: why not
Fields
error string required message string -
GET /api/notes
Parameters
limit query integer 200 The notes, newest first.
default { error, message }: why not
Fields
error string required message string -
POST /api/notes
Body
body string required 201 Add a note as the person asking.
Fields
id integer required body string required author_id string required author_name string required created_at string required updated_at string required default { error, message }: why not
Fields
error string required message string -
GET /api/notes/{id}
Parameters
id path integer required 200 One note.
Fields
id integer required body string required author_id string required author_name string required created_at string required updated_at string required default { error, message }: why not
Fields
error string required message string -
DELETE /api/notes/{id}
Parameters
id path integer required 200 Remove a note.
Fields
id integer required default { error, message }: why not
Fields
error string required message string -
PATCH /api/notes/{id}
Parameters
id path integer required Body
body string required 200 Change a note's words.
Fields
id integer required body string required author_id string required author_name string required created_at string required updated_at string required default { error, message }: why not
Fields
error string required message string
healthz 1
-
GET /healthz
200 Whether the app is up: its version, commit, environment and seconds since it started.
Fields
ok boolean required version string required commit string env string uptime integer required default { error, message }: why not
Fields
error string required message string
listings 2
-
GET /listings/{id}/kit.txt
Parameters
id path integer required 200 The listing's launch kit: every asset in one plain-text file, each marked approved or draft, with its open Fair Housing findings. Sent as an attachment.
default { error, message }: why not
Fields
error string required message string -
GET /listings/{id}/schedule.ics
Parameters
id path integer required 200 The listing's launch week as an iCalendar file: one event per step, a draft marked DRAFT. Days as typed, no time zones. Sent as an attachment.
default { error, message }: why not
Fields
error string required message string
mcp 1
-
POST /mcp
Body
jsonrpc any required id any method string required params object 200 One JSON-RPC 2.0 message to the MCP server; its tools are the actions.
default { error, message }: why not
Fields
error string required message string