State Machine Card
A printable summary of the pipeline state machine. Tape it above your monitor.
The 8 states
Section titled “The 8 states”| State | Plain meaning | Typical duration |
|---|---|---|
| NEW | Inquiry arrived. No outreach yet. | Minutes to hours (5-min SLA target). |
| CONTACTING | First outreach made. Awaiting response. | Days. |
| QUALIFIED | Motivated and shopping. Covers searching + touring. | Weeks to months. |
| COMMITTED | Buyer’s agreement signed. Working with you, not just browsing. | Days to weeks before an offer lands. |
| IN_CONTRACT | Offer accepted; in escrow. | 30–45 days (market-dependent). |
| CLOSED | Funded. Keys exchanged. | Terminal-ish (anniversary touches handled separately). |
| ARCHIVED | Set aside after no engagement. Not terminal — re-engageable. | Indefinite. |
| TRASHED | Bad contact data. Not terminal — fix the data and it re-enters NEW. | Indefinite. |
Transition diagram
Section titled “Transition diagram”The diagram shows the buyer events. Seller leads move through the same eight columns; only the three paperwork events between QUALIFIED, COMMITTED and IN_CONTRACT are different, and those are listed under Seller pipeline below.
stateDiagram-v2
direction LR
[*] --> NEW: contact_form_submission
NEW --> CONTACTING: contact_attempted
NEW --> TRASHED: bogus_contact_detected
CONTACTING --> QUALIFIED: motivation_confirmed
CONTACTING --> ARCHIVED: timeout_21d_no_response
CONTACTING --> TRASHED: bogus_contact_detected
QUALIFIED --> COMMITTED: buyer_agreement_signed
QUALIFIED --> ARCHIVED: timeout_180d_no_progress
COMMITTED --> IN_CONTRACT: contract_executed
COMMITTED --> QUALIFIED: deal_collapsed
IN_CONTRACT --> CLOSED: closing_complete
IN_CONTRACT --> QUALIFIED: contract_voided
ARCHIVED --> CONTACTING: lead_re_engaged
TRASHED --> NEW: contact_info_updated
Valid transitions (forward)
Section titled “Valid transitions (forward)”| From → To | Trigger | What it means in practice |
|---|---|---|
NEW → CONTACTING | First logged outreach (call / email / text) | The SLA clock stops here. |
NEW → TRASHED | Bogus contact detected | Junk number, fake email, duplicate. |
CONTACTING → CONTACTING | Lead responded | Stays put. Records that the conversation is two-way. |
CONTACTING → QUALIFIED | Motivation confirmed | They told you they’re serious. Pre-approval for buyers; listing intent for sellers. |
CONTACTING → ARCHIVED | No response (design target: 21 days with ≥6 attempts) | Today this is the Archive: no response button; nothing archives automatically. |
QUALIFIED → COMMITTED | Buyer’s agreement signed | Put the signed document reference in the note. |
QUALIFIED → ARCHIVED | No progress (design target: 180 days) | Today this is the Archive: no progress button. |
COMMITTED → IN_CONTRACT | Contract executed | Offer accepted, escrow opened. |
IN_CONTRACT → CLOSED | Closing complete | Deal funded. |
Reverse transitions (require a reason code)
Section titled “Reverse transitions (require a reason code)”A reverse move is a real event with analytical value — not a failure to track. The state machine enforces a reason code at the moment of transition.
| From → To | Event | Reason options |
|---|---|---|
COMMITTED → QUALIFIED | deal_collapsed | Financing fell through, Inspection issue, Buyer changed their mind, Seller withdrew, Lost to a competing offer, Agreement expired, Other. |
IN_CONTRACT → QUALIFIED | contract_voided | Financing fell through, Inspection issue, Appraisal gap, Title issue, Mutual release, Buyer withdrew, Seller withdrew, Other. |
NEW → TRASHED | bogus_contact_detected | Phone number is invalid, Email bounces, Number reaches the wrong person, Spam or bot submission, Duplicate of another lead, Other. |
CONTACTING → TRASHED | bogus_contact_detected | Same list. Often: number reaches the wrong person. |
The reason is picked from a dropdown in the action dialog and stored as a code (financing_fell_through, wrong_person, and so on). Put the specifics in the note.
Re-entry transitions (the “not terminal” cases)
Section titled “Re-entry transitions (the “not terminal” cases)”| From → To | Trigger | Notes |
|---|---|---|
ARCHIVED → CONTACTING | lead_re_engaged | The Re-engage button. The lead drops back into your active workflow. If the original agent can no longer receive leads, routing picks a new one and Scribe writes an Agent reassigned row. |
TRASHED → NEW | contact_info_updated | The Contact info fixed button, once a valid email or phone replaces the bad one. The lead re-enters the standard intake flow from the top with a fresh response clock. |
ARCHIVED and TRASHED are intentionally re-enterable. A lead in either column is recoverable; neither is a delete.
How you fire these
Section titled “How you fire these”Every trigger in the tables above is a button in the Lifecycle card on the lead’s detail page, under Next step. Forward moves are full-width buttons that show where they lead (“Log contact attempt → Contacting”); setbacks and exits sit in a smaller row underneath. The board offers the same actions through each card’s ⋯ menu and by dragging a card onto a column the state machine allows. Every route opens the same dialog, and nothing moves until you submit it.
| Stage | Forward buttons | Setbacks and exits |
|---|---|---|
| NEW | Log contact attempt → Contacting | Mark as bogus → Trashed (reason) |
| CONTACTING | Lead responded (stays), Confirm motivation → Qualified | Archive: no response → Archived, Mark as bogus → Trashed (reason) |
| QUALIFIED | Buyer agreement signed → Committed | Archive: no progress → Archived |
| COMMITTED | Contract executed → In Contract | Deal collapsed → Qualified (reason) |
| IN_CONTRACT | Closing complete → Closed | Contract voided → Qualified (reason) |
| CLOSED | none (“Closed. Nothing further to record here.”) | none |
| ARCHIVED | Re-engage → Contacting | none |
| TRASHED | Contact info fixed → New | none |
“(reason)” means the dialog has a required Reason dropdown. Log contact attempt and Lead responded ask for a channel (Call, Email, Text, In person, Other). Every dialog has an optional note and a This happened earlier… toggle for backdating.
The two Archive buttons fire the same timeout events the platform fires on its own (timeout_no_response and timeout_no_progress in the API). Scribe archives a CONTACTING lead after 21 days with no activity of any kind, and a QUALIFIED lead after 180 days, unless the brokerage has set different windows under Lead Routing. A row Scribe wrote says so and carries the idle count; a row an agent wrote carries their name.
The state machine still rejects anything not in this table. The UI never offers an illegal move, and if two people act on the same lead at once, the second one gets an error explaining the move is not valid from the lead’s current stage.
Seller pipeline
Section titled “Seller pipeline”Every lead carries a pipeline type, buyer or seller. It is set from the inquiry subject when the lead arrives (Selling and Property Valuation are seller-side, everything else is buyer-side), and staff can change it from the Add lead dialog or by editing the lead while it is still NEW or CONTACTING. After that the timeline holds one side’s paperwork and the type is locked.
Seller cards sit in the same columns as buyer cards and show a small Seller tag. NEW, CONTACTING, IN_CONTRACT, CLOSED, ARCHIVED and TRASHED offer exactly the same buttons on both sides. The difference is QUALIFIED and COMMITTED:
| Stage | Forward buttons (seller) | Setbacks and exits (seller) |
|---|---|---|
| QUALIFIED | Listing agreement signed → Committed | Archive: no progress → Archived |
| COMMITTED | Listing is live (stays), Offer accepted → In Contract | Listing withdrawn → Qualified (reason) |
| IN_CONTRACT | Closing complete → Closed | Contract voided → Qualified (reason) |
Listing is live records the listing going active on the MLS. It is a timeline row, not a column move; the lead stays in COMMITTED until an offer is accepted or the listing is withdrawn.
| Event | Fires from | Reason options |
|---|---|---|
listing_agreement_signed | QUALIFIED → COMMITTED | none |
listing_activated | COMMITTED → COMMITTED | none |
offer_accepted | COMMITTED → IN_CONTRACT | none |
listing_withdrawn | COMMITTED → QUALIFIED | Seller changed their mind, Price disagreement, Listing expired, Moved to another brokerage, Other. |
A seller lead is refused any buyer-only event (buyer_agreement_signed, contract_executed, deal_collapsed) with a 400, and a buyer lead is refused the seller events the same way. The board and the Lifecycle card only ever offer the right set, so you will only see this from the API.
On the legacy fields, a seller lead projects to the per-seller status instead of the per-buyer one: QUALIFIED is preparing, COMMITTED is listed, IN_CONTRACT is under_contract, CLOSED is closed. The per-buyer status of a linked client is left alone.
States that don’t transition out
Section titled “States that don’t transition out”CLOSED does not loop back to anything via the state machine. Anniversary touches, past-client newsletters, and referral follow-ups are handled by the alerts system, not the pipeline. A repeat transaction with a past client creates a new lead.
What counts as an “action” at each column
Section titled “What counts as an “action” at each column”| Column | Your next action is usually… |
|---|---|
| NEW | Make first contact within the SLA window. |
| CONTACTING | Follow up; aim for two-way conversation. |
| QUALIFIED | Schedule showings; share matching listings; move toward commitment. |
| COMMITTED | Run the buying process — offers, negotiations. |
| IN_CONTRACT | Coordinate inspections, appraisal, financing milestones. |
| CLOSED | Send the closing gift; queue the anniversary touch. |
| ARCHIVED | Watch for re-engagement signals; click Re-engage and reach out if the score climbs. |
| TRASHED | Nothing until the contact info is updated, then Contact info fixed. |
Related
Section titled “Related”- Temperature signals — the orthogonal axis of engagement
- Communication flags — what can and can’t go out via which channel
- Why state and temperature are separate