Skip to content

State Machine Card

A printable summary of the pipeline state machine. Tape it above your monitor.

StatePlain meaningTypical duration
NEWInquiry arrived. No outreach yet.Minutes to hours (5-min SLA target).
CONTACTINGFirst outreach made. Awaiting response.Days.
QUALIFIEDMotivated and shopping. Covers searching + touring.Weeks to months.
COMMITTEDBuyer’s agreement signed. Working with you, not just browsing.Days to weeks before an offer lands.
IN_CONTRACTOffer accepted; in escrow.30–45 days (market-dependent).
CLOSEDFunded. Keys exchanged.Terminal-ish (anniversary touches handled separately).
ARCHIVEDSet aside after no engagement. Not terminal — re-engageable.Indefinite.
TRASHEDBad contact data. Not terminal — fix the data and it re-enters NEW.Indefinite.

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
From → ToTriggerWhat it means in practice
NEW → CONTACTINGFirst logged outreach (call / email / text)The SLA clock stops here.
NEW → TRASHEDBogus contact detectedJunk number, fake email, duplicate.
CONTACTING → CONTACTINGLead respondedStays put. Records that the conversation is two-way.
CONTACTING → QUALIFIEDMotivation confirmedThey told you they’re serious. Pre-approval for buyers; listing intent for sellers.
CONTACTING → ARCHIVEDNo response (design target: 21 days with ≥6 attempts)Today this is the Archive: no response button; nothing archives automatically.
QUALIFIED → COMMITTEDBuyer’s agreement signedPut the signed document reference in the note.
QUALIFIED → ARCHIVEDNo progress (design target: 180 days)Today this is the Archive: no progress button.
COMMITTED → IN_CONTRACTContract executedOffer accepted, escrow opened.
IN_CONTRACT → CLOSEDClosing completeDeal 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 → ToEventReason options
COMMITTED → QUALIFIEDdeal_collapsedFinancing fell through, Inspection issue, Buyer changed their mind, Seller withdrew, Lost to a competing offer, Agreement expired, Other.
IN_CONTRACT → QUALIFIEDcontract_voidedFinancing fell through, Inspection issue, Appraisal gap, Title issue, Mutual release, Buyer withdrew, Seller withdrew, Other.
NEW → TRASHEDbogus_contact_detectedPhone number is invalid, Email bounces, Number reaches the wrong person, Spam or bot submission, Duplicate of another lead, Other.
CONTACTING → TRASHEDbogus_contact_detectedSame 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 → ToTriggerNotes
ARCHIVED → CONTACTINGlead_re_engagedThe 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 → NEWcontact_info_updatedThe 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.

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.

StageForward buttonsSetbacks and exits
NEWLog contact attempt → ContactingMark as bogus → Trashed (reason)
CONTACTINGLead responded (stays), Confirm motivation → QualifiedArchive: no response → Archived, Mark as bogus → Trashed (reason)
QUALIFIEDBuyer agreement signed → CommittedArchive: no progress → Archived
COMMITTEDContract executed → In ContractDeal collapsed → Qualified (reason)
IN_CONTRACTClosing complete → ClosedContract voided → Qualified (reason)
CLOSEDnone (“Closed. Nothing further to record here.”)none
ARCHIVEDRe-engage → Contactingnone
TRASHEDContact info fixed → Newnone

“(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.

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:

StageForward buttons (seller)Setbacks and exits (seller)
QUALIFIEDListing agreement signed → CommittedArchive: no progress → Archived
COMMITTEDListing is live (stays), Offer accepted → In ContractListing withdrawn → Qualified (reason)
IN_CONTRACTClosing complete → ClosedContract 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.

EventFires fromReason options
listing_agreement_signedQUALIFIED → COMMITTEDnone
listing_activatedCOMMITTED → COMMITTEDnone
offer_acceptedCOMMITTED → IN_CONTRACTnone
listing_withdrawnCOMMITTED → QUALIFIEDSeller 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.

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”
ColumnYour next action is usually…
NEWMake first contact within the SLA window.
CONTACTINGFollow up; aim for two-way conversation.
QUALIFIEDSchedule showings; share matching listings; move toward commitment.
COMMITTEDRun the buying process — offers, negotiations.
IN_CONTRACTCoordinate inspections, appraisal, financing milestones.
CLOSEDSend the closing gift; queue the anniversary touch.
ARCHIVEDWatch for re-engagement signals; click Re-engage and reach out if the score climbs.
TRASHEDNothing until the contact info is updated, then Contact info fixed.