How it works

Three steps to get from “interesting listing” to “should I buy this?”. Detailed engineering view further below for builders.

1

Add or import a property

Type an address by hand, paste a Zillow / Redfin URL, upload a CSV, or forward a wholesaler email. Connect an MLS feed once and new listings flow in automatically.

2

Analyze deal metrics instantly

The moment a property lands, the underwriting engine computes Cap Rate (Capitalization Rate), DSCR (Debt Service Coverage Ratio), Cash-on-Cash Return, monthly cash flow, and a 5-year wealth projection.

3

Identify strong opportunities

A 0–100 score plus a verdict (Strong Buy, Worth Underwriting, Maybe, Pass) tells you which deals to pursue. Top opportunities surface on your dashboard automatically.

See every step in detail

What each stage does and what you'll see in the app afterward. Skip this if you just want to get started.

+
  1. 1

    Set your buying criteria

    Tell the system what a good deal looks like to you, once.
    On /buy-box you set target locations, property types, price band, minimum DSCR / cash flow / cash-on-cash, max rehab budget, and risk exclusions (flood, tax threshold). On /settings you set the underwriting assumptions: down-payment %, interest rate, vacancy, maintenance, management, appreciation, refi LTV, hold period. These drive every score after this.
    What you'll see
    Your saved buy-box plus a default assumption set, ready to score every new property.
  2. 2

    Connect a listing source (or paste a URL, or forward an email)

    Tell the system where deals come from.
    On /sources you connect any combination of:
    • Rentcast — public-records sale listings (cleanest legal story)
    • RESO MLS — bring your own MLSGrid / Trestle / Bridge / Spark token
    • ATTOM — tax + structure enrichment
    • URL paste — Zillow / Redfin / Realtor; user-initiated, never scheduled
    • Email — forward wholesaler blasts to your private ingest+<token>@yourdomain address
    Each source declares a legal_class that drives downstream behavior: MLS rows are private-by-default, scraped rows can't be scheduled, public-API rows are freely cacheable.
    What you'll see
    Each connected source listed on the Sources page; saved searches that fetch automatically on the schedule you pick.
  3. 3

    The pipeline ingests, dedupes, and stages every listing

    Transform external data into one canonical Property row per deal.
    When a saved search runs (manually or on its cron), the orchestrator in services/ingest.py calls the adapter, normalizes every payload through the shared normalize_row() alias map (the same map the CSV importer uses), runs three-layer dedupe — by source-external-id, by canonical address hash, by content hash — and writes either a new Property or merges into an existing one. Every fetched payload is staged in raw_listings for 30 days for audit. Every successful ingest writes a UsageEvent for billing.
    What you'll see
    One row per real property in your portfolio (duplicates merged automatically), and a run log showing how many listings were fetched, how many were new, and how many were duplicates.
  4. 4

    The underwriting engine computes every metric — deterministically

    Get the truth about a deal without trusting the listing&apos;s claimed cap rate.
    For every property, analyze_property() in services/analyzer.py runs:
    • Loan amortization → monthly P&I, annual debt service
    • Operating expenses (taxes, insurance, HOA, maintenance, vacancy, mgmt, repairs)
    • NOI, cap rate, monthly cash flow, cash-on-cash, DSCR
    • Break-even occupancy, GRM, price per sqft
    • 5-year projection: equity paydown + appreciation + cumulative cash flow → wealth_hold
    • Refi scenario: ARV at hold-period × LTV − remaining loan = cash-out potential
    • Scale-to-next: does the refi cash-out cover the down-payment on the next deal?
    Three scenarios — conservative / base / aggressive — adjust vacancy, maintenance, rent, and appreciation around the same formulas. Missing inputs don't crash; they degrade data_confidence instead.
    What you'll see
    A full financial snapshot per property — conservative, base, and aggressive — visible on the property page.
  5. 5

    The scoring engine assigns 0–100 with a transparent breakdown

    Tell you which deals are worth your weekend.
    Seven weighted positives (cashflow 20, cash-on-cash 20, DSCR 15, buy-box fit 15, price advantage 10, rent upside 10, refi potential 5) minus penalties for red flags (up to −15) and data confidence (up to −10). The verdict bands:
    • ≥80 — Strong Buy
    • 65–79 — Worth Underwriting
    • 50–64 — Maybe
    • <50 — Pass
    Every contribution persists with its weight, target, and the value scored against it. The detail page renders this as a bar chart with failure reasons listed inline.
    What you'll see
    A 0–100 score with a verdict on every property, plus an itemized list of red flags the engine raised.
  6. 6

    AI writes the memo, the realtor questions, and the negotiation angles

    Turn the snapshot into something you can actually act on.
    services/ai_summary.py sends the snapshot + listing description to the AI with a strict system prompt: never invent numbers, only cite the snapshot, no hype language, return JSON. Output: a one-paragraph summary, “why it works”, “what could go wrong”, realtor questions, negotiation angles, documents to request. If your Anthropic key is unset, a deterministic mock generates the same output structure using the real numbers — the UX doesn't change. System prompt is ephemeral-cached, so re-runs pay only for the delta.
    What you'll see
    A plain-English AI summary on every property page plus a one-click printable investment memo.
  7. 7

    The dashboard ranks your top opportunities

    Open the laptop, see today&apos;s top deals, ignore everything else.
    /dashboard shows portfolio KPIs (total properties, Strong Buys, average cash flow / DSCR / cash-on-cash, portfolio cash needed), a top-deals table sorted by score, a recent-imports list, the deal pipeline by stage, a watchlist panel, and a portfolio-wide activity feed. /propertiesgives you the full sortable / filterable table. /compare stacks 2-4 properties side-by-side across every metric.
    What you'll see
    Top-ranked deals on your dashboard. One click takes you to the full property workspace.
  8. 8

    Per-property workspace: chat, offers, notes, activity, outreach

    Move a deal from &quot;interesting&quot; to &quot;under contract&quot; without leaving the page.
    On /properties/[id] you get:
    • Pipeline controls — move through lead → analyzing → offer_made → under_contract → closed_won/lost.
    • Score breakdown — every sub-contribution, every failure reason.
    • Deal chat — agentic AI with tools (get_snapshot, compare_scenario, get_buy_box_fit, list_notes). Asks like “Run this aggressive — does DSCR still clear 1.25?” resolve via deterministic tool calls, never invented numbers.
    • Offer builder — DSCR-banded suggested price + earnest money + contingencies. AI writes the cover letter and counter-strategy.
    • Outreach agent — drafts the initial inquiry to the listing agent, ingests their replies, drafts your responses. You approve before each send.
    • Notes & activity — pinnable user notes; append-only audit log.
    What you'll see
    Five panels stacked under each property: pipeline controls, score breakdown, deal chat, offer builder, and outreach — every action recorded in the activity log.
  9. 9

    The Outreach Agent handles the back-and-forth

    Stop being your own assistant.
    Click New thread on any property, fill in the listing agent's email, click Draft initial inquiry. The agent writes a polite, concise email asking for the 3-4 things it actually needs to underwrite (rent roll, opex, taxes/insurance, condition disclosures). You edit in place and click Approve & send. The reply lands at reply+<token>@yourdomain — HMAC-verified, routed back to the right thread. Click Draft reply and the loop continues. The agent never commits on price, financing, or timing — it always defers to you.
    What you'll see
    One thread per agent contact on the Outreach page, with every email you and the agent exchange in one place — recorded in the activity log.
  10. 10

    The scheduler runs everything on autopilot

    Don&apos;t make humans click buttons for routine work.
    A separate beat container polls saved_searches every 30s, compares each search's cron expression to the current time, advancesnext_run_at forward before dispatching (so two beats can't double-fire), and enqueues runs on Redis. Stuck runs are auto-reaped after 30 minutes; raw payloads are TTL'd at 30 days. The arq worker pool drains the queue. Prometheus counters at /metrics let you watch fetch rate, dedupe ratio, and queue depth.
    What you'll see
    A run-history log on every saved search showing when it last ran, how many listings it fetched, and how many were new.

The whole flow in one sentence

Listings come in → duplicates are removed → every property gets a full underwriting and a 0–100 score → the AI writes a memo and handles back-and-forth with the listing agent → you decide which deals to pursue. Every paid AI action is metered against your plan, and every AI feature has a free deterministic fallback so the product works end-to-end even without an Anthropic key.