Follow-ups & sales credit
Knowing who is worth a call is only half of it. Follow-ups turn what Stitchwork knows into a short list with an owner and a day — and when the sale lands, the credit goes to the people who actually earned it.
Why this exists
Everything else in Stitchwork is evidence: what somebody browsed, how interested they are, which baskets are still open, what a colleague knows about them. None of it says what anyone has committed to doing about it, or whether they did.
A follow-up is that missing piece — a customer, a person who owes them something, a day it is owed by, the reason, and afterwards what actually happened. It is deliberately not a dashboard card: a list that changes every time you open it, where nothing belongs to anybody and nothing can be finished, is a list nobody opens twice.
Today
Today is the screen to open before taking your coat off, in the order of the calls: who asked to be rung, what is overdue or due on your list, who is walking in, what is coming up in the next fortnight — birthdays, anniversaries, a client's other dates — for your clients and anyone nobody looks after, and who came back to the website since yesterday and is nobody's yet. It is deliberately not configurable. Team members land on it when they sign in; owners and admins land on the dashboard, and anyone sent a link lands where it points.
On a shop-floor iPad or phone, Add to Home Screen keeps Stitchwork there as an app: it opens on Today, full screen, with its own icon.
The list
Follow-ups in the sidebar opens on your work, not the workspace's — grouped overdue, today, this week, later. Three tabs: Mine, Unassigned (work nobody has taken yet), and Everyone.
- Take it claims a piece of unassigned work.
- Log outcome closes one — as done, or dismissed as not worth doing.
Follow-ups arrive four ways: somebody raises one from a customer's page, an AI connection proposes one, somebody works a list on Leads, or a customer asks for one themselves. That last case is the warmest kind there is — they asked — and it happens two ways: a phone number typed into a nudge opens a follow-up against whoever the browser is already stitched to, and a message through your contact form opens one due today, carrying their own subject line.
Where a nudge callback comes from a browser nobody has a name for yet, it cannot become a follow-up — there is no customer record to owe it to. Those wait in the callback queue until somebody rings them and takes an email address.
You can raise a follow-up from any customer's page, and you can only have one open per customer at a time. That is enforced in the database rather than by good manners: "we owe this person a call" is one obligation however many signals produced it, and a list that grows faster than anyone can work it stops being used.
Closing one requires saying what happened. A "done" with nothing behind it is a pressed button, and a manager reading the week back learns nothing from a column of them. The same is asked of a dismissal — "not worth doing" is a judgement, and the reason is the most useful thing about it six weeks later.
When the customer answers it themselves
Some of the people on your list buy before anybody gets to the phone. The follow-up that was right on Monday is a trap by Wednesday — whoever picks it up opens with "I see you didn't finish your order" to somebody who bought yesterday.
So Stitchwork retires those itself. When a sale lands, any open follow-up it answered is closed as settled, with a sentence saying what was bought and that nobody had made contact. You will see it on the row and in the weekly review; nobody has to do anything.
| A follow-up settles when | Why that condition |
|---|---|
| Nobody raised it by hand | Only work proposed by an AI connection or a rule. Somebody who raised one themselves may know something no table does — a conversation at a show, a promise made on the phone. |
| Nobody has claimed it | Once it is on a person's list, whether it is still worth doing is their call, not ours. |
| Nobody has engaged them | No note, quote or appointment since it was raised. The purchase may well be the result of that work, and retiring the row would erase the trail of a call that worked — along with the credit for whoever made it. |
| They spent enough | Where the follow-up is about a specific sum — an abandoned basket, an open quote — the later spend has to cover it, in the same currency. A £30 cushion does not settle a £4,200 sofa. Where it is about no particular sum ("they have gone quiet"), any purchase settles it, because that was the objective. |
Nobody made that call, so nothing is credited for it. A settled follow-up carries no closer at all — enforced in the database, not by convention, because sales credit counts closing a follow-up as an act that earns a share, and a settled row that named somebody would quietly pay them for a call they never made.
It is counted apart from dismissals in the weekly review for the same reason. A dismissal is a judgement somebody made; this is demand that converted with no help at all, which is a genuinely useful number and a misleading one if the two are added together.
Settling frees the customer up: it says this obligation expired, not that the person is finished with. You can raise a new follow-up for them the same day.
Reasons to get in touch
Between one purchase and the next, a considered sale has moments a good associate would not miss, and a busy one does. Each night Stitchwork raises a follow-up for each of them, on the list of whoever looks after the client, with the reason in words — what happened and when, never what to say:
- A date coming up — a birthday, an anniversary or another date on the client's record, a week ahead by default: "Birthday on Sat 10 Oct — in 7 days."
- Aftercare — a fortnight after an order is handed over by default: "Handed over 14 days ago: Walnut sideboard (order 1042). Check it has settled in." When an order was handed over is stamped by the database, and an order imported as already fulfilled takes its own date — a year of history does not become this morning's deliveries.
- A missed appointment — one marked as a no-show: "Missed their appointment on Fri 2 Oct at 11:00 (Bath). Worth a call to rebook."
- A quote about to lapse — three days before a sent quote's valid-until date by default, carrying the quote's value, so only a purchase that covers it settles it.
- A repair not collected — a week after a job was marked ready to collect: "Their Omega Seamaster has been ready to collect for 9 days." This one is always on; see Repairs.
Each moment is raised once, however often the sweep runs. A customer who already has a follow-up open does not get a second: the moment waits, and is raised once that one is done if it is still worth raising. A night the sweep does not run loses nothing — each kind looks back a week. How far ahead (or after) each comes, and whether it comes at all, is in Settings → Retention → Reasons to get in touch: dates 1–60 days ahead, aftercare 1–365 days after, lapsing quotes 1–30 days before, and missed appointments on or off.
GET /api/v1/settings/touchpoints
PATCH /api/v1/settings/touchpoints {"dates_days": 10, "aftercare_days": null, "no_shows": true, "quote_expiry_days": 3}
It runs with the nightly bin/opportunity-sweep.php, after the day's purchases
have settled what they answer.
Where the work lands
A follow-up you raise is yours. One raised by an AI connection — or by anyone who does not name an owner — is routed from the customer's own records, in this order:
- Whoever looks after them — the client's associate — at the store their other records point to, or at a store the associate works when they cannot see that one. A client of yours is yours however long since you last met.
- The associate who raised their open quote, at the store they raised it at.
- Whoever saw them at their last appointment, at that store.
- Any recent quote.
- Their last order — which names a store but nobody in particular.
Nothing is guessed. The name comes off a record your workspace already holds, and every routed follow-up carries the sentence explaining it: "Priya Shah raised quote Q-1042, still open". Whoever it lands on can hand it back in one click.
Two rules make that fair, and they are different on purpose:
- A store is sticky. Somebody who has only ever dealt with your Bath showroom belongs to Bath, whenever they last came in.
- A person is not. An owner is only inherited from something in the last 90 days, because people leave and change store — and a customer on the wrong person's list looks handled, which is worse than one on nobody's. An open quote is the exception: it is a live obligation whoever raised it, at any age.
Somebody who has left the workspace, or moved to another store, does not inherit their old customers: the next person on the customer's records is tried, and when there is nobody the work keeps the store and loses the owner, so somebody there can claim it.
The weekly review
GET /api/v1/follow-ups/review?days=7 returns what was raised, done,
dismissed, settled, what is still open and what is overdue — and
how much of it your own AI connection proposed. It ships with the list rather than after it, because a work list
nobody reviews is the dashboard card that failed, with extra steps.
Sales credit
When a sale lands, Stitchwork splits the credit across the people who earned it. This is a different question from the campaign attribution on the reports page, and the two are never added together: there is no exchange rate between a Google click and a showroom conversation. One order, two ledgers.
What earns credit
Exactly three acts:
- Raising a quote
- Holding an appointment
- Closing a follow-up with an outcome
Credit attaches to the sale, never to activity. Notes earn nothing, and neither does raising a follow-up — a note is a record and an unworked follow-up is a plan. Repeated acts of the same kind by the same person count once, so whoever revises a quote most does not win. If credit could be earned by doing things rather than by selling, people would do things, and the customer file would become a scoreboard.
Credit follows who did it, never who the work was assigned to. A follow-up routed to one person and closed by another belongs to whoever closed it.
How it splits
The opener takes 40%, the closer takes 40%, and anyone in between shares the remaining 20%. With two people that is a clean 50/50.
Priya raised the quote, 3 Jun ......... 40%
Tom held the appointment, 18 Jun ....... 20%
Priya closed the follow-up, 2 Jul ...... 40%
→ Priya 80% · Tom 20%
One model, not five. The campaign report shows five side by side because attribution is an opinion; a commission is a payment, and it has to be sayable in one sentence to the person it pays.
What keeps it honest
- The trail is frozen; the money is not. The touches are stored as they stood when the sale closed, so nobody's pay changes because a colleague tidied a record. Shares are fractions and no amount is cached — so a refund reduces what was earned without anybody re-running anything.
- A sale nobody touched pays nobody. It is never quietly handed to the nearest rep.
- Credit is paid on the net, not the gross. Record how much came back on an order — through the API, a CSV column, or the order page — and every share follows it down. If a sale is part-refunded and nobody has recorded the amount, it is held out of the run and listed for you to settle: paying the full amount would overpay and paying nothing would underpay, so neither is guessed. Your dashboard's Unsettled refunds card counts exactly these.
- Someone who leaves keeps what they earned. The record of a sale they closed stays true.
When somebody disagrees
They will. An owner or admin can set a split by hand from the order — and what the policy originally calculated stays on the record beside it, with who changed it and why. A reason is required; an unexplained change to somebody's pay is refused rather than discouraged.
A draft to open with
A follow-up can carry a proposed_message: a couple of sentences whoever
raised it thinks the customer should hear, written at raising time while the evidence
was on screen. An agent proposing a follow-up can attach one;
so can an integration raising work for a colleague. It renders on the card with a
Copy button while the work is open, and that button is the whole of
what it does — the associate pastes it into their own email or phone, makes it theirs,
and sends it there. Stitchwork holds no outbound channel to a customer, so a draft is a
starting point, never a send: nothing an agent writes reaches a customer unless a
person carries it the last mile. Like the reason beside it, it cannot be edited after
raising, and settlement, routing, credit and discard all ignore it — words nobody sent
must not change what a follow-up is worth.
The API
GET /api/v1/follow-ups?who=mine&status=open
POST /api/v1/follow-ups {"customer_id": 12, "reason": "…", "due_on": "2026-08-28",
"proposed_message": "…"}
POST /api/v1/follow-ups/{id}/close {"status": "done", "outcome": "…"}
POST /api/v1/follow-ups/{id}/assign {"assignee_id": "me"}
GET /api/v1/follow-ups/review?days=7
GET /api/v1/sales-credit?from=2026-07-01&to=2026-07-31
GET /api/v1/orders/{id}/credit
POST /api/v1/orders/{id}/credit {"shares": {"7": 0.5, "8": 0.5}, "reason": "…"}
Credited earnings come back per currency and are never totalled across them, the same rule every other money figure in Stitchwork follows. There is no exchange rate in the system, so a combined number would be invented — and an invented number on a commission run is worse than one on a dashboard.
The same figures live on two screens. Sales → Sales credit is the run: pick a period and read credited sales per person, per currency, with the part-refunded sales awaiting a recorded refund listed beneath rather than silently missing — asking for a period freezes the credit on any sale in it nobody had opened yet, so the run is complete however the orders arrived. And every order's own page carries Who earned this sale: the split, the frozen trail behind it, and — for an owner or admin — the ruling form, which asks for the reason because somebody is being paid differently on the strength of it. What the policy computed stays beside every ruled share.
A credit record cannot be deleted — it is the evidence behind a payment, and removing it is how a dispute stops being resolvable. A follow-up can be, and that is a different thing: see clearing the list.
Follow-up changes fan out as webhooks
(follow_up.created, .done, .dismissed,
.settled, .updated), and every change to a follow-up or a credit
split is written to your audit log with who made it — or as
the system, for a settlement nobody made.
Clearing the list
Closing a follow-up asks what happened, on purpose — that is what makes the weekly review a record rather than a count of pressed buttons. But some rows have no outcome to record: a sweep that proposed badly, test data from before a pilot went live, an AI suggestion that is obviously wrong. Making somebody type "not worth doing" forty times is not an audit trail, and the forty dismissals it leaves behind sit on forty customers' files reading as though your team engaged with them.
So discarding is a separate act from dismissing:
- Dismiss — somebody looked at real work and judged it not worth doing. The judgement is worth keeping, so the row stays with its reason.
- Discard — the row should never have existed. It is removed outright, and nothing is left on the customer's file.
Bin it on any row removes that one — your own, or anybody's if you are an owner or admin. Clear the list, for owners and admins, removes a set: unassigned AI suggestions, or every open follow-up.
Three things a discard will never do. It cannot touch a completed follow-up — that carries an outcome somebody wrote, and a sale may be credited from it, so deleting it would quietly change what somebody is owed. It cannot run unaimed by accident: a request with no filter removes nothing unless it explicitly says so. And no AI connection can do it — an agent that could delete its own suggestions could remove the evidence of its own mistakes.
One line goes in your audit log for the whole operation — who cleared what, when, and how it was chosen — rather than one per row. That line is the only record of it, which is the trade being made deliberately: nothing survives on the customer, and the workspace log answers where it went.
DELETE /api/v1/follow-ups/{id}
POST /api/v1/follow-ups/discard {"source": "agent", "unassigned": true}
POST /api/v1/follow-ups/discard {"raised_before": "2026-08-01"}
POST /api/v1/follow-ups/discard {"ids": [4, 9, 17]}
POST /api/v1/follow-ups/discard {"confirm": "all"}
What your AI can do with this
An MCP connection can read the list
(list_follow_ups) and add to it (create_follow_up). It cannot
close, reassign or re-date one — what happened on a call is a fact only the person who
made it holds. The agent proposes work; a person does it and records what came of it.
Because it can only ever add, and because one follow-up can be open per customer, a nightly agent sweep is safe to run: it converges rather than filling your team's lists with copies of its own suggestions.
An agent running each morning does not need to re-check whether the
people it flagged are still worth calling. Settlement has already
retired the ones who bought — as the order landed, not on a schedule — so the open list is
current by the time it reads it. What it can usefully do is ask for
status: "settled" and report what was overtaken by events: nobody made those
calls, and it is the honest denominator for how good its suggestions were.
When your agent raises a follow-up from an abandoned basket or an open quote, it passes the figure along with it. That is what lets the row be settled by a purchase that actually covers it, rather than by any purchase at all — the difference between retiring a £4,200 sofa correctly and retiring it because somebody bought a cushion.