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 The audit trail, newest first; `before` pages back by id.

    Parameters

    limitqueryinteger
    beforequeryinteger

    200 The audit trail, newest first; `before` pages back by id.

    default { error, message }: why not

    Fields

    errorstringrequired
    messagestring
  • GET /api/audit/{id} One row of the audit trail.

    Parameters

    idpathintegerrequired

    200 One row of the audit trail.

    Fields

    idintegerrequired
    atstringrequired
    who_idstring | null
    who_namestring | null
    roleenum(anon, user, admin)required
    resourcestringrequired
    verbstringrequired
    targetstring | null
    allowedenum(0, 1)required
    outcomestringrequired

    default { error, message }: why not

    Fields

    errorstringrequired
    messagestring
  • GET /api/listings The listings, newest first, each with how many phrases the Fair Housing check flags. Filter by status and search the address.

    Parameters

    limitqueryinteger
    statusqueryenum(all, active, under_contract, sold, coming_soon, off-market, needs-approval)
    qquerystring

    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

    errorstringrequired
    messagestring
  • POST /api/listings 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.

    Body

    addressstringrequired
    bedsintegerrequired
    bathsnumberrequired
    sqftintegerrequired
    lotstringrequired
    yearintegerrequired
    priceintegerrequired
    featuresstring[]required
    toneenum(classic, warm, bold)
    paletteenum(navy, forest, burgundy, charcoal, teal)
    agent_namestringrequired
    brokeragestringrequired
    licensestringrequired
    agent_phonestringrequired
    agent_emailstringrequired
    open_housesobject[]

    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

    idintegerrequired
    author_idstringrequired
    author_namestringrequired
    addressstringrequired
    bedsintegerrequired
    bathsnumberrequired
    sqftintegerrequired
    lotstringrequired
    yearintegerrequired
    priceintegerrequired
    featuresstring[]required
    toneenum(classic, warm, bold)required
    paletteenum(navy, forest, burgundy, charcoal, teal)required
    agent_namestringrequired
    brokeragestringrequired
    licensestringrequired
    agent_phonestringrequired
    agent_emailstringrequired
    open_housesobject[]required
    photosstring[]required
    headshotstring | nullrequired
    statusenum(coming_soon, active, under_contract, sold, withdrawn, expired)required
    sold_priceinteger | nullrequired
    was_priceinteger | nullrequired
    created_atstringrequired
    updated_atstringrequired
    showingsobject[]
    assetsobject[]required

    default { error, message }: why not

    Fields

    errorstringrequired
    messagestring
  • GET /api/listings/{id} 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.

    Parameters

    idpathintegerrequired

    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

    idintegerrequired
    author_idstringrequired
    author_namestringrequired
    addressstringrequired
    bedsintegerrequired
    bathsnumberrequired
    sqftintegerrequired
    lotstringrequired
    yearintegerrequired
    priceintegerrequired
    featuresstring[]required
    toneenum(classic, warm, bold)required
    paletteenum(navy, forest, burgundy, charcoal, teal)required
    agent_namestringrequired
    brokeragestringrequired
    licensestringrequired
    agent_phonestringrequired
    agent_emailstringrequired
    open_housesobject[]required
    photosstring[]required
    headshotstring | nullrequired
    statusenum(coming_soon, active, under_contract, sold, withdrawn, expired)required
    sold_priceinteger | nullrequired
    was_priceinteger | nullrequired
    created_atstringrequired
    updated_atstringrequired
    showingsobject[]
    assetsobject[]required

    default { error, message }: why not

    Fields

    errorstringrequired
    messagestring
  • DELETE /api/listings/{id} Remove a listing, its assets and its photos.

    Parameters

    idpathintegerrequired

    200 Remove a listing, its assets and its photos.

    Fields

    idintegerrequired

    default { error, message }: why not

    Fields

    errorstringrequired
    messagestring
  • PATCH /api/listings/{id} 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

    Parameters

    idpathintegerrequired

    Body

    kindenum(mls, social_short, social_medium, social_carousel, social_status, social_price, flyer, email)
    textstring
    toneenum(classic, warm, bold)
    statusenum(coming_soon, active, under_contract, sold, withdrawn, expired)
    sold_priceinteger | null
    factsobject
    photosobject
    restoreinteger
    approvedboolean
    seenstring

    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

    idintegerrequired
    author_idstringrequired
    author_namestringrequired
    addressstringrequired
    bedsintegerrequired
    bathsnumberrequired
    sqftintegerrequired
    lotstringrequired
    yearintegerrequired
    priceintegerrequired
    featuresstring[]required
    toneenum(classic, warm, bold)required
    paletteenum(navy, forest, burgundy, charcoal, teal)required
    agent_namestringrequired
    brokeragestringrequired
    licensestringrequired
    agent_phonestringrequired
    agent_emailstringrequired
    open_housesobject[]required
    photosstring[]required
    headshotstring | nullrequired
    statusenum(coming_soon, active, under_contract, sold, withdrawn, expired)required
    sold_priceinteger | nullrequired
    was_priceinteger | nullrequired
    created_atstringrequired
    updated_atstringrequired
    showingsobject[]
    assetsobject[]required

    default { error, message }: why not

    Fields

    errorstringrequired
    messagestring
  • POST /api/listings/{id}/showings 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.

    Parameters

    idpathintegerrequired

    Body

    datestring
    agentstring
    interestenum(not_interested, maybe, interested, offer_likely)required
    feedbackstring

    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

    idintegerrequired
    showingintegerrequired

    default { error, message }: why not

    Fields

    errorstringrequired
    messagestring
  • DELETE /api/listings/{id}/showings/{showing} Remove a showing the agent logged.

    Parameters

    idpathintegerrequired
    showingpathintegerrequired

    200 Remove a showing the agent logged.

    Fields

    idintegerrequired

    default { error, message }: why not

    Fields

    errorstringrequired
    messagestring
  • GET /api/notes The notes, newest first.

    Parameters

    limitqueryinteger

    200 The notes, newest first.

    default { error, message }: why not

    Fields

    errorstringrequired
    messagestring
  • POST /api/notes Add a note as the person asking.

    Body

    bodystringrequired

    201 Add a note as the person asking.

    Fields

    idintegerrequired
    bodystringrequired
    author_idstringrequired
    author_namestringrequired
    created_atstringrequired
    updated_atstringrequired

    default { error, message }: why not

    Fields

    errorstringrequired
    messagestring
  • GET /api/notes/{id} One note.

    Parameters

    idpathintegerrequired

    200 One note.

    Fields

    idintegerrequired
    bodystringrequired
    author_idstringrequired
    author_namestringrequired
    created_atstringrequired
    updated_atstringrequired

    default { error, message }: why not

    Fields

    errorstringrequired
    messagestring
  • DELETE /api/notes/{id} Remove a note.

    Parameters

    idpathintegerrequired

    200 Remove a note.

    Fields

    idintegerrequired

    default { error, message }: why not

    Fields

    errorstringrequired
    messagestring
  • PATCH /api/notes/{id} Change a note's words.

    Parameters

    idpathintegerrequired

    Body

    bodystringrequired

    200 Change a note's words.

    Fields

    idintegerrequired
    bodystringrequired
    author_idstringrequired
    author_namestringrequired
    created_atstringrequired
    updated_atstringrequired

    default { error, message }: why not

    Fields

    errorstringrequired
    messagestring

healthz 1

  • GET /healthz Whether the app is up: its version, commit, environment and seconds since it started.

    200 Whether the app is up: its version, commit, environment and seconds since it started.

    Fields

    okbooleanrequired
    versionstringrequired
    commitstring
    envstring
    uptimeintegerrequired

    default { error, message }: why not

    Fields

    errorstringrequired
    messagestring

listings 2

  • GET /listings/{id}/kit.txt 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.

    Parameters

    idpathintegerrequired

    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

    errorstringrequired
    messagestring
  • GET /listings/{id}/schedule.ics 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.

    Parameters

    idpathintegerrequired

    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

    errorstringrequired
    messagestring

mcp 1

  • POST /mcp One JSON-RPC 2.0 message to the MCP server; its tools are the actions.

    Body

    jsonrpcanyrequired
    idany
    methodstringrequired
    paramsobject

    200 One JSON-RPC 2.0 message to the MCP server; its tools are the actions.

    default { error, message }: why not

    Fields

    errorstringrequired
    messagestring
↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs