How to Create a Client Workspace and Welcome Pack When a Stripe Subscription Starts

When a new Stripe subscription begins, verify the event by signature, then fan out in parallel to provision a Monday.com client board, post an internal Slack kickoff, and call a reusable welcome-pack subworkflow that emails onboarding materials through Resend.

What This Integration Does

For a professional-services firm, every new retainer or subscription kicks off the same scramble: someone has to spin up a project board, tell the team in chat, and send the client their onboarding pack. This Spojit workflow does all three the moment a customer's Stripe subscription goes live, so a signed deal turns into a ready-to-work client space within seconds and nothing slips through the cracks.

Stripe posts a customer.subscription.created event to your workflow's Webhook trigger URL. Spojit verifies the request signature against your Stripe signing secret, parses the JSON body, and immediately returns 202 with an executionId so Stripe sees a fast acknowledgement. A Parallel node then runs three independent branches at once: a Monday.com board provisioning branch, a Slack kickoff-message branch, and a Subworkflow branch that calls your shared welcome-pack workflow. Because the branches are independent, the whole onboarding finishes about as fast as the slowest branch rather than the sum of all three. Stripe retries delivery if it ever does not get a fast response, so turn on dedup (below) to keep a retried event from provisioning a second board.

Prerequisites

  • A Stripe connection (API key) for any read-back you need, plus a Stripe webhook endpoint you will point at this workflow and its signing secret (starts with whsec_).
  • A Webhook signing connection set to the Custom scheme, holding your Stripe whsec_ secret, so Spojit can verify the Stripe-Signature header. See Setting Up a Webhook Connection.
  • A Monday.com connection and a board template (or an existing board) you want each client board cloned from, plus the workspace and column titles you will populate.
  • A Slack connection with access to your internal kickoff channel (for example #client-onboarding).
  • A Resend connection with a verified sending domain, used inside the reusable welcome-pack subworkflow.
  • A separate, already-built welcome-pack workflow in your workspace that you can call as a Subworkflow (this tutorial builds the parent; Step 6 covers the child's contract).

Step 1: Add a Webhook trigger and verify the Stripe signature

Start a new workflow and set the Trigger type to Webhook. Copy the generated workflow URL. In the trigger's Signing connection field, select the Webhook signing connection you created with the Custom scheme and your Stripe whsec_ secret. This makes Spojit validate the Stripe-Signature header on every request and reject anything that does not match, so only genuine Stripe events run the workflow.

Turn on dedup and point it at Stripe's event id so retried deliveries do not re-provision. The parsed body is available downstream as {{ input }}. A customer.subscription.created event looks like this:

{
  "id": "evt_1Q9aBc...",
  "type": "customer.subscription.created",
  "data": {
    "object": {
      "id": "sub_1Pz...",
      "customer": "cus_OabC123",
      "status": "active",
      "items": { "data": [ { "price": { "nickname": "Growth Retainer" } } ] }
    }
  }
}

Step 2: Confirm this is a subscription-created event

Stripe sends many event types to one endpoint, so add a Condition node right after the trigger that checks {{ input.type }} equals customer.subscription.created. Route the true branch into the rest of the workflow and leave the false branch unconnected so unrelated events end quietly.

If you want the client's name and email rather than just the customer id, add a Connector node in Direct mode on the Stripe connector using the get-customer tool, mapping its id field to {{ input.data.object.customer }}. Bind the result to a variable like customer so later steps can read {{ customer.name }} and {{ customer.email }}.

Step 3: Fan out with a Parallel node

Add a Parallel node and connect it to the true output of the Condition. Create three branches: Provision board, Notify team, and Send welcome pack. Each branch runs concurrently and cannot see the others' variables, so anything a branch needs (the customer name, email, plan nickname) must come from upstream variables such as {{ customer.email }} or {{ input.data.object.items.data.0.price.nickname }}. The Parallel node completes only when all three branches finish. See Using Parallel Nodes for branch behavior.

Step 4: Branch A - provision a Monday.com client board

In the Provision board branch, add a Connector node in Direct mode on the Monday.com connector using the create-item tool. Set board_id to the board you track clients on, set item_name to the client name (for example {{ customer.name }}), and pass your column values as JSON to populate plan, start date, and status columns:

{
  "board_id": "1234567890",
  "item_name": "{{ customer.name }}",
  "column_values": {
    "text_plan": "{{ input.data.object.items.data.0.price.nickname }}",
    "status": { "label": "Onboarding" },
    "date_start": { "date": "{{ input.data.object.start_date }}" }
  }
}

If you want an immediate activity note on the new board item, follow it with a second Direct-mode Monday.com node using create-update, passing the new item's id from the previous step's output. Bind the create result to board_item so you can reference its id.

Step 5: Branch B - post an internal Slack kickoff

In the Notify team branch, add a Connector node in Direct mode on the Slack connector using the send-message tool. Set the channel to your onboarding channel and write a templated text that names the client and plan so the team can pick up the work:

{
  "channel": "#client-onboarding",
  "text": ":tada: New client onboarding started: *{{ customer.name }}* on the *{{ input.data.object.items.data.0.price.nickname }}* plan. Board is being created and the welcome pack is on its way."
}

If you would rather have the intelligent layer compose a richer summary from the event, switch this node to Agent mode and describe the post in a prompt; Direct mode is cheaper and fully predictable, so prefer it for a fixed message like this.

Step 6: Branch C - call the reusable welcome-pack subworkflow

In the Send welcome pack branch, add a Subworkflow node and pick your existing welcome-pack workflow in the Workflow field. Pass the data the child needs through the Input field, keeping the contract small and explicit:

{
  "clientName": "{{ customer.name }}",
  "clientEmail": "{{ customer.email }}",
  "plan": "{{ input.data.object.items.data.0.price.nickname }}"
}

Inside that child workflow (built once, reused by every plan), the entry trigger reads this input, then a Connector node in Direct mode on the Resend connector uses the send-email tool to deliver the onboarding materials from your own verified domain. Map to to {{ input.clientEmail }}, set from to your onboarding address, and template the subject and HTML body with {{ input.clientName }} and {{ input.plan }}. The child's final output returns to this Parallel branch, and the parent's Parallel node completes once it lands. Keeping the email logic in a Subworkflow means every workflow that onboards a client (Stripe, manual signups, imports) sends the exact same pack. See Using Subworkflow Nodes.

If you instead want a quick internal copy from Spojit's built-in mail service rather than your own domain, you can add a Send Email node anywhere in the parent. Use the Resend connector's send-email when the message must come from your branded sending domain.

Tips

  • Keep the three Parallel branches independent. If the Slack post must wait for the Monday board id, that dependency belongs in the same branch as the board, not in a separate one.
  • Pull the customer name and email once in Step 2 and reuse the customer variable across branches, rather than calling get-customer inside each branch.
  • Use a Subworkflow for the welcome pack so a copy change ships to every caller at once; the child takes effect immediately for all parents.
  • Ask Miraxa, the intelligent layer across your automation, to scaffold the fan-out for you with a prompt like "Add a Parallel node after the Condition with three branches: a Monday.com create-item node, a Slack send-message node, and a Subworkflow node," then fine-tune each branch in the properties panel.

Common Pitfalls

  • Skipping the signing connection. Without the Stripe whsec_ secret on a Custom-scheme Webhook signing connection, the trigger cannot verify the Stripe-Signature header and either rejects or runs unverified traffic.
  • No dedup. Stripe retries delivery on slow or failed responses; without dedup keyed on the event id, a retry creates a second Monday board and a duplicate welcome email.
  • Handling every event type. One Stripe endpoint receives many event types. Without the Step 2 Condition on {{ input.type }}, invoices and payment events would also trigger onboarding.
  • Resend domain not verified. The send-email tool will fail if the sending domain on your Resend connection is not verified, and external recipients of any Send Email node must be on the org allowlist in Settings > General > Email recipients.

Testing

Use Stripe's test mode to create a subscription, or send a sample customer.subscription.created payload from the Stripe webhook tester to your workflow URL. Watch the run in the execution history: confirm the trigger verified the signature, the Condition took the true branch, and all three Parallel branches succeeded. Check that one new item appeared on the Monday board, one message landed in the Slack channel, and the subworkflow shows as its own execution-history entry that sent the Resend email. Send the same event twice to confirm dedup blocks the duplicate before you enable the workflow for live traffic.

Learn More

Did this answer your question? Thanks for the feedback There was a problem submitting your feedback. Please try again later.