A B2B SaaS client in Bengaluru signed about 60 free trials a week and converted 9% to paid. Their median time-to-activation — first real workflow run inside the product — was 11 days, which is longer than their 14-day trial. We built one n8n automation that listens to Stripe, drips through Kit (formerly ConvertKit), and hands warm trials to a human in HubSpot. Median activation dropped to under 3 days. This is the whole build, with node JSON, credentials, error handling, and the ₹ monthly cost.
The Answer in 60 Words
Stripe's customer.subscription.created webhook hits an n8n Stripe Trigger when a trial starts. n8n creates the subscriber in Kit, adds them to a behaviour-tagged sequence, and upserts a HubSpot contact. A second Stripe Trigger on customer.subscription.trial_will_end (fires 3 days out) flips a HubSpot deal stage and pings the AE. Activation events from the product API short-circuit the drip.
Why This Matters Now (August 2025)
Stripe and Kit both shipped changes that made this cleaner. The Kit API v4 (the rebrand from ConvertKit) settled the subscriber-and-sequence endpoints we rely on. And n8n's Stripe Trigger now auto-registers the webhook with your Stripe account when you activate the workflow — no manual endpoint pasting in the Stripe dashboard. We tested this on n8n v1.62, self-hosted on a Hetzner CX22, in late July 2025.
The activation gap is the real problem, though. A trial that converts on day 11 of a 14-day window is a coin flip. Pull activation forward and the conversion math changes on its own.
What You'll Need (Prerequisites)
- n8n v1.6x or newer (self-hosted or Cloud) with a public HTTPS URL for webhooks
- A Stripe account with at least one trialing subscription product
- A Kit (ConvertKit) account on a plan with API access and one sequence created
- A HubSpot account (free CRM tier works) with a private app token
- Your product's own "activation" event available via webhook or a polled API
- About 90 minutes, and a test customer you can push through Stripe test mode
How Do You Connect Stripe, Kit, and HubSpot Credentials in n8n?
Three credential types, set up once under Credentials → New in n8n.
Stripe: n8n's Stripe Trigger uses your Stripe API key (restricted key is fine — it needs read on customers/subscriptions and write on webhook endpoints). Paste the secret key; n8n handles webhook registration when the workflow goes active.
Kit: Kit v4 uses an API key in the X-Kit-Api-Key header. There's no official Kit node for every action, so we use the HTTP Request node with a Header Auth credential. Create a Header Auth credential named "Kit v4", header name X-Kit-Api-Key, value your key.
HubSpot: Create a private app in HubSpot (Settings → Integrations → Private Apps) with scopes crm.objects.contacts.write and crm.objects.deals.write. n8n's HubSpot node takes that token as an App Token credential.
The Trigger Config: Two Stripe Events, Not One
The flow has two entry points. Splitting them keeps each branch readable and lets you retry one without re-running the other.
Trigger A — trial starts. Stripe Trigger node listening for customer.subscription.created. We filter inside n8n for subscriptions where status === 'trialing' so paid signups skip the drip.
Trigger B — trial about to end. A second Stripe Trigger on customer.subscription.trial_will_end. Per Stripe's webhook docs, this event fires three days before the trial period ends, which is exactly the window where a human nudge converts.
Here's Trigger A as exported node JSON:
{
"parameters": {
"events": ["customer.subscription.created"]
},
"id": "stripe-trigger-trial-start",
"name": "Stripe — Trial Started",
"type": "n8n-nodes-base.stripeTrigger",
"typeVersion": 1,
"position": [240, 300],
"credentials": {
"stripeApi": { "id": "1", "name": "Stripe account" }
}
}The first node after the trigger is an IF node that drops anything not actually trialing:
{
"parameters": {
"conditions": {
"string": [
{
"value1": "={{ $json.data.object.status }}",
"operation": "equals",
"value2": "trialing"
}
]
}
},
"name": "IF — Is Trialing",
"type": "n8n-nodes-base.if",
"typeVersion": 1,
"position": [460, 300]
}How Do You Add a Trial User to a Kit Sequence in n8n?
Kit v4 has a rule: the subscriber must exist before you can add them to a sequence. So it's two HTTP Request calls — create, then enrol. Per the Kit sequences API, the enrol endpoint is POST /v4/sequences/{sequence_id}/subscribers.
The create-subscriber HTTP Request node, with the behaviour tag set from the Stripe plan:
{
"parameters": {
"method": "POST",
"url": "https://api.kit.com/v4/subscribers",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"email_address\": \"{{ $json.data.object.customer_email }}\",\n \"fields\": { \"plan\": \"{{ $json.data.object.items.data[0].price.nickname }}\", \"trial_start\": \"{{ $now.toISO() }}\" }\n}"
},
"name": "Kit — Create Subscriber",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [680, 220],
"credentials": {
"httpHeaderAuth": { "id": "2", "name": "Kit v4" }
}
}Then the enrol call uses the sequence ID for the trial drip. We keyed three sequences off the plan tier so an entry-tier trial gets a different cadence than a top-tier one. Behaviour beats the calendar, though — see the short-circuit below.
What Drip Cadence Actually Converted?
The cadence matters less than people expect, but a few choices moved the needle. Here's the self-serve sequence we shipped, with the reasoning per email.
The one surprising result: removing the day-7 "halfway through your trial" email entirely raised conversion slightly. It was noise. Fewer, better-timed emails beat a fuller calendar. If you take one thing from this cadence, make it the day-2 nudge gated on the activation event — that single conditional did most of the work.
Upserting the HubSpot Contact and Deal
The HubSpot node upserts a contact by email, so a returning trial doesn't create a duplicate. We set a lifecyclestage of opportunity and stamp the trial end date as a custom property the AE can sort on.
{
"parameters": {
"resource": "contact",
"operation": "upsert",
"email": "={{ $json.data.object.customer_email }}",
"additionalFields": {
"lifecycleStage": "opportunity",
"customProperties": {
"customProperty": [
{ "property": "trial_plan", "value": "={{ $json.data.object.items.data[0].price.nickname }}" },
{ "property": "trial_end_date", "value": "={{ $json.data.object.trial_end }}" }
]
}
}
},
"name": "HubSpot — Upsert Contact",
"type": "n8n-nodes-base.hubspot",
"typeVersion": 2,
"position": [900, 220],
"credentials": {
"hubspotAppToken": { "id": "3", "name": "HubSpot App" }
}
}The Activation Short-Circuit (The Part That Actually Moved the Number)
Here's the unintuitive bit. The drip isn't the thing that cut activation to 3 days. The short-circuit is.
When the product fires its own "first workflow run" event, a small n8n webhook catches it, removes the subscriber from the nurture sequence in Kit, and moves the HubSpot deal straight to "activated." The drip stops nagging an activated user, and the AE sees a hot, self-served account a week earlier than before. Activated trials converted at 31% versus 11% for the calendar-only cohort.
How Do You Handle Errors in a Webhook Chain Like This?
Webhook chains fail in boring, predictable ways: a third-party 429, a malformed email, a duplicate delivery. Three guardrails caught all of ours.
1. Error Workflow. Set a global Error Workflow in n8n settings that posts the failed execution URL to a Slack channel. You find out before the customer does.
2. Retry on the HTTP nodes. Kit and HubSpot calls get "Retry On Fail" with 3 attempts and a 5-second wait. Most 429s clear on the second try.
3. Dead-letter the email. If a Kit create fails after retries, we route to a NoOp + a row in a Google Sheet "failed_onboarding" tab. A daily cron re-attempts. Nothing silently vanishes.
{
"parameters": {
"method": "POST",
"url": "https://api.kit.com/v4/sequences/{{ $json.sequence_id }}/subscribers",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"sendBody": true,
"jsonBody": "={ \"email_address\": \"{{ $json.email }}\" }"
},
"name": "Kit — Enrol in Sequence",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"retryOnFail": true,
"maxTries": 3,
"waitBetweenTries": 5000,
"position": [1120, 220]
} What Does This Cost Per Month?
The flow itself is cheap. The cost is mostly the tools you already pay for.
A single Hetzner CX22 runs all three of these August workflows at once, so the server cost is a shared slice, not a per-flow cost. n8n Cloud Starter is an option if you'd rather not self-host. Either way, this is cheaper than one hour of the developer time it replaces every week.
When NOT to Build This
Skip it if you sign fewer than ~10 trials a week. Below that, a founder reading every signup in Slack and sending a personal email converts better than any automation — the human touch is the product at low volume. Skip it too if your product has no measurable activation event; without the short-circuit you're just sending a fixed drip, and a Mailchimp automation does that with no n8n at all. And don't build it if your trial is shorter than 5 days — there isn't room for a behaviour-based cadence to breathe.
Real Example: The Bengaluru SaaS Client
A 14-person B2B SaaS company (project-management tooling for agencies) came to our AI and automation team with the 9% conversion problem. We shipped this flow in 6 working days. The number that moved leadership wasn't conversion — it was AE time. The two-person sales team stopped manually checking Stripe every morning and got a prioritised "these 4 trials are hot, these 2 are cold" view in HubSpot. We saw the same pattern building Radiant Finance's lead pipeline — the lift came from routing humans to the warm accounts, not from sending more email. We've since wired the same Stripe-to-CRM pattern into other engagements; it's the sibling of our 90-second sales brief workflow and our Stripe + ConvertKit + Slack client onboarding flow.
The two-person sales team's morning changed in a concrete way. Before the flow, the first 30 minutes of each day was an AE clicking through Stripe and the product admin to guess who was worth a call. After, HubSpot opened to a sorted list: trials past their activation event at the top, cold ones flagged for a last-chance email. That half-hour, across two reps over a quarter, is roughly 60 hours of selling time the flow handed back — more than the build cost to recover.
"We thought we had a conversion problem. We had a speed problem. Trials that touched real value in 3 days closed themselves."
The architecture mirrors how we build internally too. On TalkDrill, our in-house English-speaking app with 5,000+ users, the same event-driven onboarding logic decides when a new user is ready for a nudge versus when to stay out of their way.
Frequently Asked Questions
Does the n8n Stripe Trigger register the webhook automatically?
Yes. When you activate a workflow with a Stripe Trigger node, n8n calls Stripe's API and registers the webhook endpoint for you. You don't paste a URL into the Stripe dashboard. Deactivating the workflow removes the registration. This is why a public HTTPS URL on n8n is a prerequisite.
When exactly does customer.subscription.trial_will_end fire?
Stripe sends it three days before the trial period ends. If the trial is shorter than three days, it fires at creation. It also fires immediately if you end a trial with trial_end=now. We use it as the trigger for the human sales handoff at T-minus-3.
Why use Kit's HTTP Request node instead of a dedicated node?
Kit v4 endpoints (the rebrand from ConvertKit) move faster than n8n's bundled node updates. The HTTP Request node with a Header Auth credential using X-Kit-Api-Key hits any v4 endpoint directly, so you're never blocked waiting for node support.
How do I stop the drip when a user activates?
Add a separate n8n webhook that your product calls on the activation event. It removes the subscriber from the Kit sequence and advances the HubSpot deal stage. This short-circuit is what cut median activation from 11 days to under 3 — the drip alone didn't.
Is the server slice really the full cost?
That's the incremental infra cost — a shared slice of one Hetzner CX22 running several workflows. Stripe webhooks are free, and Kit and HubSpot are subscriptions the client already paid for. n8n Cloud Starter is an alternative if you don't want to self-host.
Can this work with Razorpay instead of Stripe?
Yes, with one change: Razorpay's subscription webhooks differ from Stripe's, so you swap the Stripe Trigger for a generic Webhook node and parse Razorpay's payload. We cover the Razorpay side in our payment-failed recovery workflow.
Want this trial-to-paid flow built on your stack?
We ship a working, self-hosted n8n onboarding workflow — Stripe or Razorpay, your email tool, your CRM — for Indian SaaS teams in 7 working days. Suitable if you sign 10+ trials a week and convert under 15%. No slides — just your funnel and our honest take.
Book a 20-min Call
Written by Hrishikesh Baidya, CTO at Softechinfra. Questions about your onboarding stack? Email contact@softechinfra.com.
