Skip to content

Payments + Plans

StartKit.AI uses either Stripe or Lemon Squeezy for your payment provider and we have setup instructions for both.

Stripe

  1. Make sure you have your Stripe Account set up for receiving payments.
  2. Turn on Stripe’s Test Mode
  3. Create a new product and copy the Price ID

How to find the Stripe price id

  1. Paste the Price ID into the config/plans.yml file for the respective plan, in the price_id field.

Stripe Webhooks

Webhooks are how Stripe lets you know that you’ve received a payment. In the case of StartKit.AI, we have an API route that you can provide to Stripe which will provision a users’ account after they pay using the limits set in the plans.yml file.

  1. Go to Developers -> API Keys and copy the Secret key, enter it into your .env
.env
STRIPE_API_KEY=
  1. Go to Developers -> Webhooks and add the endpoint for https://<your_startkit_url>/api/webhooks/payments (you can change this url later if you don’t know your domain yet).

You should listen to the following events at a minimum (you can add more later if you want):

  • checkout.session.completed
  • customer.subscription.deleted
  • customer.subscription.updated

Testing locally in development

It’s possible to test the Stripe webhooks locally by using the Stripe CLI.

  1. Install Stripe CLI (more install instructions here).
brew install stripe/stripe-cli/stripe
  1. In the Stripe dashboard go to Developers -> Webhooks -> Add an endpoint -> Test in a local environment.
  2. After logging into the Stripe CLI run this command to forward Stripe webhook events to your local server:
stripe listen --forward-to localhost:1337/api/webhooks/payments
  1. Copy the signing secret from the CLI and enter it into your .env
.env
STRIPE_WEBHOOK_SECRET=

Now you can either trigger events manually with the CLI:

stripe trigger payment_intent.succeeded

Or you can test purchasing a plan using Stripe test payment methods.

In production

  1. In test mode of the Stripe Dashboard, copy your products to live mode and copy the Price ID into your plans.yaml file (see the Stripe Setup section above).
  2. Turn off test mode in your Stripe dashboard.
  3. In Developers -> API Keys copy the Secret key and add it to STRIPE_API_KEY= in your production environment variables.
  4. In Developers -> Webhooks create the live webhook at https://<your_startkit_url>/api/webhooks/payments if you haven’t already. Click the webhook, reveal the live signing secret, and enter in STRIPE_WEBHOOK_SECRET= in your production environment variables.
.env.production
STRIPE_API_KEY=
STRIPE_WEBHOOK_SECRET=

Stripe Webhook Events

StartKit.AI implements the following Stripe webhooks and actions them:

/server/api/webhooks/stripe.js
switch (type) {
case 'checkout.session.completed': {
// ✨ The user completed the checkout and paid successfully
// Here we provision access to your product based on the Stript product ID
handleCheckoutCompleted(data.object);
break;
}
case 'checkout.session.expired': {
// ⏲️ The user opened the checkout but did not complete the payment
// (optional): Send a cart expired email
break;
}
case 'customer.subscription.updated': {
// 🔀 The user changed their subscription.
// If the plan was upgraded or downgraded then we update the limits
//
// If the plan was canceled we make a note of this on the user
// as this event is received before the end of the cencellation
// period. A 'customer.subscription.deleted' event will be fired
// when the billing period is finished
// This means you can handle when an account is coming up for cancellation
//
// If the plan was reactivated after being cancelled then we make a note
// of this on the user and ignore the subscription cancelled event from before.
handleSubscriptionUpdated(data.object, data.previous_attributes);
break;
}
case 'customer.subscription.deleted': {
// ❌ The user deleted their subscription
// We remove the users' access to the product
handleSubscriptionDeleted(data.object);
break;
}
}

Feel free to add any other webhook actions that you need into this switch statement.

Lemon Squeezy

  1. Make sure you have your Lemon Squeezy Account set up for receiving payments.
  2. Turn on Lemon Squeezy’s test mode (this is turned on by default if you didn’t set your store live yet).
  3. Create a new product and copy the Product ID.

How to find the Lemon Squeezy product id

  1. Paste the Product ID into the config/plans.yml file for the respective plan, in the price_id field (StartKit uses the price_id variable name but we need the Product Id from Lemon Squeezy).

Lemon Squeezy Webhooks

Webhooks are how Lemon Squeezy lets you know that you’ve received a payment. In the case of StartKit.AI, we have an API route that you can provide to Lemon Squeezy which will provision a users’ account after they pay using the limits set in the plans.yml file.

  1. Go to Settings -> API, create an API key and enter it into your .env
.env
LEMONSQUEEZY_API_KEY=
  1. Go to Settings -> Webhooks and add the endpoint for https://<your_startkit_url>/api/webhooks/payments (you can change this url later if you don’t know your domain yet).

Generate a signing secret like this:

Terminal window
openssl rand -base64 24 | tr -dc A-Za-z0-9 | head -c 40

Enter the signing secret into both your webhook setup and your .env:

.env
LEMONSQUEEZY_WEBHOOK_SECRET=

You should listen to the following events at a minimum (you can add more later if you want):

  • subscription_created
  • subscription_updated
  • subscription_cancelled
  • subscription_resumed
  • subscription_expired

Testing locally in development

It’s possible to test the Lemon Squeezy webhooks locally by using a tool like ngrok to forward the requests to your localhost URL.

Or you can simulate webhook events from the Lemon Squeezy dashboard - see their developer guide for more information.

In production

  1. In test mode of the Lemon Squeezy Dashboard, copy your products to live mode and copy the Product IDs into your plans.yaml file (see the Lemon Squeezy Setup section above).
  2. Turn off test mode in your Stripe dashboard.
  3. In Settings -> API create a production API key and add it to LEMONSQUEEZY_API_KEY= in your production environment variables.
  4. In Settings -> Webhooks create the live webhook at https://<your_startkit_url>/api/webhooks/payments if you haven’t already. Copy the live signing secret you enter, and enter in LEMONSQUEEZY_WEBHOOK_SECRET= in your production environment variables.
.env.production
LEMONSQUEEZY_API_KEY=
LEMONSQUEEZY_WEBHOOK_SECRET=

Lemon Squeezy Webhook Events

StartKit.AI implements the following Lemon Squeezy webhooks and actions them:

/server/api/webhooks/lemonsqueezy.js
switch (meta.event_name) {
case 'subscription_created': {
// The user completed the checkout and paid successfully
// ✨ Provision access to your product
await handleCheckoutCompleted(data.attributes);
break;
}
case 'subscription_updated': {
// The user changed their subscription.
// ✨ If the plan was upgraded or downgraded change access to your product
handleSubscriptionUpdated(data.attributes);
break;
}
case 'subscription_cancelled': {
// The user canceled their subscription
// Set the subscription to canceled but keep access until the end date
handleSubscriptionCanceled(data.attributes);
break;
}
case 'subscription_resumed': {
// The user resumed a previously canceled subscription
// Set the subscription to resumed and remove end date
handleSubscriptionReactivated(data.attributes);
break;
}
case 'subscription_expired': {
// The user deleted their subscription
// 🚫 Remove access to your product
handleSubscriptionDeleted(data.attributes);
break;
}
}

Feel free to add any other webhook actions that you need into this switch statement.