How the Lead Pipeline works
The Kanban CRM board over your conversations — stages, stats, revenue values, and why it is not your Reach contact list.
How the Lead Pipeline works
The Lead Pipeline is a Kanban CRM board built on top of your conversations. Open it at Wallu Assist → Lead Pipeline in the sidebar.
Every card on the board is a conversation from your Inbox — the same record, not a copy. There is no separate "lead" object being created behind the scenes.
<!-- SCREENSHOT: Lead Pipeline board showing the six stage columns with lead cards -->
It is not your Reach contact list
Read this part carefully, because the naming invites the wrong assumption.
- The Lead Pipeline stores everything inside the
tags field of each conversation, as underscore-prefixed pseudo-tags (_leadScore:8, _leadStage:qualified, _value:4900). It is served by /api/pipeline.
- The contact database behind email campaigns is a completely separate
Lead table — email addresses, subscription status, consent records, and list membership.
These two systems are not joined by anything. A contact in your Reach list does not appear on the pipeline board, and dragging a card to Closed Won does not touch that contact's record. If you are looking for one CRM object that unifies a conversation and an email contact, it does not exist in Wallu today.
The practical consequence: the pipeline is a view of people who messaged you, not of people on your mailing list.
The board
Six stages, in order:
- New Leads (
new)
- Qualified (
qualified)
- In Progress (
in_progress)
- Proposal (
proposal)
- Closed Won (
won)
- Lost (
lost)
Drag a card between columns, or open a card and use the Stage dropdown. Both save immediately.
Any conversation that has never been scored sits in New Leads and shows a - instead of a score.
The board only loads 200 conversations
The board fetches the 200 most recently active conversations and nothing else. If you have more than that, the older ones simply never appear, and there is no paging control or "load more" button. The search box filters only what is already loaded.
What the four stats actually mean
The numbers across the top are computed from the loaded cards, not from your whole account:
- Total Leads — how many cards are currently loaded (capped at 200). This is not your total conversation count.
- Pipeline Value — the sum of Revenue Value across Closed Won cards only. Despite the name, deals sitting in Proposal contribute nothing to it.
- Avg Score — the mean AI score across loaded cards. Unscored cards count as 0, so this reads artificially low until most cards have been scored.
- Win Rate — Closed Won cards divided by loaded cards.
Revenue value
Open a card and set Revenue Value ($) in the detail panel. The field is stored in cents — the API takes 4900 to mean $49.00. Setting it to 0 removes the value.
This is a number you type in. Nothing sets it automatically, and it is not connected to Stripe, to orders, or to any purchase event.
<!-- SCREENSHOT: Lead detail sidebar with the AI score card, stage dropdown and Revenue Value field -->
Deleting a lead destroys the conversation
This is the one place where the CRM framing is actively misleading, so be careful.
Delete Lead and Delete All do not "remove the card from the board". They delete the underlying conversation row and every message in it. The conversation disappears from your Inbox as well. There is no undo and no archive.
Delete All removes every card currently loaded (up to 200). It ignores the search box — filtering the view does not narrow what gets deleted. The confirmation dialog shows the exact count it is about to destroy; read it before confirming.
If you only want a conversation out of your way, resolve it in the Inbox instead of deleting it here.
Lead scoring, stage rules, and the pipeline API
How AI scoring reads a conversation, which platforms the bulk scorer skips, the re-score gotcha, and the full /api/pipeline reference.
Lead scoring, stage rules, and the pipeline API
How AI scoring reads a conversation
Scoring sends the conversation to the model and asks for a score from 1 to 10:
- 1-3 Cold — browsing, no buying intent, general questions
- 4-6 Warm — showing interest, asking about features or products
- 7-9 Hot — asking about pricing or availability, wants to buy
- 10 Ready to close — explicitly wants to purchase or sign up
The model reads the 30 most recent messages in the thread, plus the platform and the customer's name. Reading the newest messages is deliberate: buying signals land at the end of a conversation, so scoring the oldest 30 would grade the opening small talk of any long thread.
Each run returns four things, all written back into the conversation's tags:
- the score (1-10)
- 2-4 auto-tags, drawn from a fixed list: price-inquiry, product-interest, support-question, returning-customer, high-intent, comparison-shopping, budget-conscious, urgent, complaint, feedback, partnership, referral
- a one-line summary of the lead's intent
- a suggested stage
Each run replaces the previous score, summary, and timestamp rather than stacking on top of them, so the detail panel always shows the newest summary. Any row still carrying stale duplicates from an older build heals the next time it is scored.
The AI Score button skips most of your conversations
The AI Score button in the header runs a bulk pass, and that pass is far narrower than the board it sits above. It only covers conversations on Instagram, Facebook, and WhatsApp. It processes at most 100, and it skips any conversation already scored within the last 24 hours.
Web-chat and Discord conversations — for most accounts, the large majority of the board — are never touched by this button, no matter how many times you press it. This is why the board can look mostly unscored even after a bulk run completes and reports success.
The workaround: open any individual card and use Re-Score with AI in the detail panel. That path has no platform restriction and works on a conversation from any channel, including web and Discord. It is one card at a time.
If your leads arrive mainly through Instagram DMs, the bulk button covers you. Otherwise, treat scoring as a manual, per-card action.
Re-scoring overwrites the stage you set by hand
Stage is stored in the same place the scorer writes to, and the scorer rewrites it.
If you drag a card to Closed Won and later re-score that card, the AI's suggested stage replaces your manual stage. If the AI returns no stage at all, the card falls all the way back to New Leads.
So: score first, sort into stages afterwards. Do not re-score a board you have already organised by hand unless you are willing to redo it. Revenue Value and notes survive re-scoring — only the stage is overwritten.
The second score, which nothing displays
Wallu contains a second, event-based scoring system that awards points to Reach contacts — for example a DM received, a comment, or a purchase. It writes those points onto the contact's record.
Treat it as unavailable. It has no screen: not the pipeline board, not the Inbox detail panel. Most of its defined rules are never fired, and it only records anything at all when an incoming sender happens to match an existing contact. It is also a completely different number from the 1-10 pipeline score described above — do not confuse the two.
API reference
Base path /api/pipeline. All routes require your session cookie and are scoped to your account.
GET /api/pipeline/pipeline — the 200 most recently active conversations as leads. Returns { "leads": [...] }.
POST /api/pipeline/score/:conversationId — score one conversation now. Returns { score, tags, summary, stage }. Works on any platform.
POST /api/pipeline/score-all — bulk pass (Instagram/Facebook/WhatsApp only, max 100, 24h skip). Returns { scored, errors }.
GET /api/pipeline/:conversationId/score — the stored score.
PATCH /api/pipeline/:conversationId/stage — body { "stage": "qualified" }.
PATCH /api/pipeline/:conversationId/value — body { "value": 4900 }, in cents.
PATCH /api/pipeline/:conversationId/notes — body { "notes": "..." }.
PATCH /api/pipeline/:conversationId/tags — body { "tags": [...] }.
DELETE /api/pipeline/:conversationId — deletes the conversation and all its messages.
DELETE /api/pipeline/bulk/delete — body { "ids": [...] }. Returns { success, deleted }.
Things that will bite you
- The stage endpoint does not validate its input. It accepts any string. Send a stage that is not one of the six valid ids and the card matches no column — it vanishes from the board while still existing in the database. Valid ids:
new, qualified, in_progress, proposal, won, lost.
- The tags endpoint replaces the entire tag array with whatever you send. It does not merge. Anything you omit is gone, including the score, summary, stage, notes, and revenue value, since all of them live in that same array.
GET /:conversationId/score never 404s. For a conversation that does not exist or is not yours, it returns the default { score: 0, summary: "Not scored yet", stage: "new", autoTags: [] }. Do not read that as "exists but unscored".
createdAt in the pipeline response is last-activity time, not creation time. It is bumped whenever a new message arrives.
- The mutating routes return
404 {"error":"Conversation not found"} when the conversation is not yours. DELETE /bulk/delete returns 400 {"error":"No IDs provided"} for an empty list.
Endpoints with no interface
These work over the API and are returned by GET /api/pipeline/pipeline, but no screen in the app reads or writes them. If you need them, you need to call the API yourself:
- Notes (
PATCH /:id/notes) — stored and returned as notes, never rendered.
- Manual tags (
PATCH /:id/tags) — returned as manualTags. The Tags row in the detail panel shows AI auto-tags only.
- Stage history — every stage change is recorded and returned as
stageHistory, but nothing displays it.
For handing a conversation to a human instead of tracking it as a deal, see Tickets. For the conversation view itself, see Unified Inbox. New to the platform? Start at Getting Started.