Kicklace, an AI-powered CRM for micro SaaS
Stripe CRM for SaaS
Kicklace takes Stripe's webhook itself. This is what happens to a payment after that: the person it lands on, the stage it moves them to, the email you may send, and what an AI can do with it.
Six things, in this order
A payment in Stripe is one line in a dashboard. This is what the same payment is in Kicklace, from the customer who made it to the follow-up it starts.
01
A Stripe customer
Pays you. Stripe posts what happened.
02
A Kicklace person
One record, from their first anonymous visit.
03
The subscription
Started, renewed, refunded, cancelled.
04
The lifecycle
Purchaser, Repeat, Trial, Churned — from the events.
05
The email
What you may send them, and why.
06
The AI
A summary, a chart, an automation — from a sentence.
01
The Stripe customer
Kicklace takes Stripe's webhook itself. Settings → Integrations → Stripe gives you one address of the form https://<your Kicklace>/api/webhooks/stripe/…, which you paste into Stripe → Developers → Webhooks. Stripe shows the signing secret when the endpoint is made, so that is the second step here rather than the first. There is nothing to deploy and no handler to write.
Every post is verified before anything is read: Stripe's Stripe-Signature header is an HMAC-SHA256 of the raw body with the timestamp in front of it, compared in constant time, with five minutes of tolerance. Until the secret is in, nothing is taken. Every post — kept, ignored or refused — is one line in your website's heartbeat, in English, so you can see it arriving.
02
The Kicklace person
The record a payment lands on is usually older than the payment, and that is the whole point of it.
Most Stripe objects carry an email address, and that is the first thing Kicklace looks for: the checkout's customer details, the session's address, the receipt address, the charge's billing details. A subscription carries no address at all — only a customer id — so the id is written down as a stripe_customer identity the first time an event arrives with both, and from then on a subscription event finds the same person.
If there is neither, nothing happens: Kicklace will not invent a person out of a billing id it has never seen with an address beside it. The post is answered and ignored, and the reason is on the heartbeat.
When the address is one Kicklace already knows, the payment lands on the record that address belongs to — the visitor who read your pricing page in July, the person who joined your list in August, the account your server told Kicklace about last week. That is one record with one timeline, and the earliest first touch is always the one that is kept, so the campaign that brought them in survives the purchase.
03
The subscription
What each Stripe event becomes. Kicklace reads the ones that mean something about a person and ignores the rest.
- checkout.session.completed
- A purchase, with the amount in whole currency units on the person's timeline. So is payment_intent.succeeded, and so is invoice.paid — which is what a renewal really is.
- customer.subscription.created
- A subscription started. If Stripe says the status is trialing, it is a trial starting instead: the status decides, not the dates.
- customer.subscription.updated
- A renewal — but only when Stripe's previous_attributes carries current_period_end. Every other update to a subscription is a change to a plan, not a payment.
- customer.subscription.deleted
- A cancellation. It is the one event in Kicklace that can move somebody down the lifecycle.
- charge.refunded
- A refund on the timeline. It moves nobody.
- checkout.session.expired
- Somebody left a checkout without paying. It moves nobody, and an automation can answer it.
- Anything else
- Answered 200 and ignored. A refusal would only make Stripe try again for three days.
Nothing lands twice. A payment is keyed by the invoice where there is one, then by the payment intent, then by the event's own id, and that key is the idempotency key on the row — which is why one payment that arrives as a checkout, a payment intent and an invoice is one purchase on the timeline and not three. Stripe retrying a delivery lands once for the same reason.
A purchase carries its amount in whole currency units — Stripe sends minor units, and the currencies that have none are known — so a chart of revenue is counting real money.
04
The lifecycle
Nobody sets a stage by hand. It comes from what the person did, which is why a board of it describes your business rather than what somebody remembered to update.
- 1Visitor
Seen on the website
- 2Subscriber
Gave an email address
- 3Account
Created an account
- 4Activated
Did the first real thing in the product
- 5Purchaser
First purchase
- 6Repeat
Bought again
The lifecycle a new workspace starts with. Sample stages, not a customer's.
A purchase moves somebody to Purchaser. A second one moves them to Repeat. Two more stages are switched on in one press under Settings → Pipelines, because a product with no trial and no subscription should not carry two empty columns for ever: Trial, which a trial starting moves somebody into, and Churned, at the end.
A cancellation is the one move down, and it is worth saying plainly. From Purchaser or Repeat it moves somebody to Churned: they were paying and they stopped. From Trial it moves them back to Account instead — a trial that ended is not a customer who left, and putting them beside the customers who did would make every churn figure you draw wrong. From anywhere else it moves nobody. And it is not the end of the road: a purchase from Churned takes them back up to Purchaser.
An event whose stage your workspace has not got — a trial starting where there is no Trial stage — is recorded and moves nobody, with no error anywhere. The event is what happened; the stage is only what Kicklace makes of it.
05
The email
A payment is something the person did, and that is what decides whether you may write to them about it.
An email caused by what somebody just did needs no list. A thank-you after a purchase, a note when a subscription is cancelled, a receipt of your own — Kicklace calls those transactional, and an automation may send one because the trigger is the person's own action: a purchase, a sign-up, a support message, a reply, or an event your servers post. There is no list to leave, so there is no unsubscribe link in it; instead the footer says in one line why they are receiving it.
A newsletter to your customers is the other kind, and it needs their consent. A list send goes only to people who joined that list, with the sentence each of them read stored word for word beside the subscription, and a one-click unsubscribe in every email. Somebody who has only ever paid you is not on a list, and Kicklace will not put them on one for you.
Between the two there is a floor that no setting turns off: Kicklace only emails a person who has been in touch — who bought, signed up, wrote in, replied, or joined a list. Anybody else is refused, in a sentence saying so.
06
The AI
The last link is the one that makes the first five worth having: everything above is a record a model can read, and a sentence is how you ask for something to be done with it.
- A paragraph about the customer. Every person and organization carries one, written from that record's own timeline, with the next step on its own line. It is rewritten when something happens to them, and it never quotes another record.
- A chart, from a question. “Revenue by source over the last 90 days” becomes a chart on your dashboard. The model writes a spec that Kicklace validates and runs; it never writes SQL and never touches your data.
- An automation, from a sentence. “When a subscription is cancelled, wait a day, then draft an email asking why” becomes an automation you read as When · Wait · Only if · Then, and turn on yourself.
- A starter, in one press. The SaaS starter makes a Product updates list, five emails to rewrite in your own words, and five automations — welcome, check in, thank you for paying, ask why on a cancellation, and a task when somebody goes quiet. Everything it installs arrives paused.
Every one of those is a draft or a proposal until a person says so. Each automation says which of three it is — drafts only, proposes and you approve, or runs alone — and sending is what you approve, never what an AI decides.
Questions
- Do I need to write a Stripe webhook handler?
- No. Kicklace takes Stripe's webhook itself: you paste one address into Stripe → Developers → Webhooks and bring back the signing secret. If you would rather post from a handler of your own, the events API takes a purchase with an idempotency key and the result is the same — but do one or the other, or the payment lands twice.
- What happens if the same payment arrives twice?
- It lands once. Every purchase is keyed by the invoice where there is one, then the payment intent, then Stripe's own event id, and that key is the idempotency key on the row. So a checkout, a payment intent and an invoice for one payment are one purchase on the timeline, and a Stripe retry changes nothing.
- How does Kicklace know which person a subscription belongs to?
- A subscription event carries a Stripe customer id and no address, so Kicklace writes that id down as an identity the first time an event arrives carrying both. From then on subscription events find the same person. If it has seen neither the address nor the id before, the post is answered and ignored: it will not invent a person out of a billing id.
- Can I email everyone who bought something?
- Only what they agreed to. An email caused by the purchase itself — a thank-you, a receipt, a note when a subscription is cancelled — is transactional and needs no list. A newsletter to your customers is a list send, and it goes to the people who joined that list, with the sentence each of them read stored word for word.
- Does a cancellation delete anything?
- No. It moves the person to Churned if you have switched that stage on, and their timeline, their consent records and their first touch stay exactly as they were. A purchase from Churned moves them back up to Purchaser: somebody who left and came back is a customer again.
- What if I do not use Stripe?
- Post the purchase yourself. One call with an email address, a value and an idempotency key does everything the Stripe receiver does, including the lifecycle move, so an automation written for a purchase never has to know where the money came from. GitHub Sponsors arrives as a purchase too, through its own receiver.
Read next
Join the waitlist
We are onboarding one company at a time. Leave your email and we will let you know when your workspace is ready.