Bootstrapping Guide
Integrate payments to your first Saas and accept payments with @polar.shwhy polar sh
Well, Stripe is invite only in India and Lemon Squeezy needs pre-approved by Stripe plus Stripe onboarding sucks too, I messaged them had some meetings like months at end they said I need some kind of business registration bro it's side hustle I don't know I need a business I just need to implement payment easy fast and get paid easy peasy, now comes merchant of record who accept payment on behalf of use and do all the tax and stuff we dont care about and pay us cool right? There's one doing the same thing: polar.sh (an open-source Merchant of Record). There are alternatives too, but I didn't try them, so let's stick to polar.sh for now.
Plus their UI is top notch

just 3 easy steps
- Login to polar sh, add a product and get the accessToken
- A button named buy now
- Webhook handling for subscription events
first steps
Assuming you have auth setup in your project, you would have the client email in your state. Now login to Polar.sh - their onboarding process is very simple. Select your country carefully. Initially, I messed up the first time and selected US, which caused some issues as my bank is in india. But their support is one of the best (support@polar.sh), so make sure to select the country where your bank account is located.
once the account is done go to polar or sandbox.polar.sh(testing) and after that go settings → general scroll down to
bottom there is developer create new tokens
Create one, Copy the token and save it somewhere safe. You won’t be able to see it
again.
now setup your env
//.env.local POLAR_ACCESS_TOKEN = polar_oat_your_token_here
install the deps
pnpm install @polar-sh/sdk @polar-sh/nextjs
Setup client
// src/polar.ts import { Polar } from "@polar-sh/sdk"; export const api = new Polar({ accessToken: process.env.POLAR_ACCESS_TOKEN!, server: "sandbox", // Use this option if you're using the sandbox environment - else use 'production' or omit the parameter });
Now Create a buy now button
const BuyNowButton = () => { const handleBuyViaPolar = () => { const productId = "get_from_polar_dashboard"; const checkoutUrl = new URL("/checkout", window.location.origin); checkoutUrl.searchParams.set("products", productId); // this is optional but recommended like when you open the checkout page this email will be autofilled in the checkout page and any additional parameters will be returned in webhook call for you to play with if (isAuthenticated && user) { if (user.email) { checkoutUrl.searchParams.set("customerEmail", user.email); } if (user.id) { checkoutUrl.searchParams.set("customerExternalId", user.id); } } window.open(checkoutUrl.toString(), "_blank"); }; return <button onClick={handleBuyViaPolar}>Buy this</button>; };
Now when user clicks on this button it will navigate to /checkout
Checkout Route
// src/app/checkout/route.ts import { Checkout } from "@polar-sh/nextjs"; export const GET = Checkout({ accessToken: process.env.POLAR_ACCESS_TOKEN!, successUrl: "/confirmation?checkout_id={CHECKOUT_ID}", // the polar sh will navigate back to this URL after the payment is successful server: "sandbox", // Use this option if you're using the sandbox environment - else use 'production' or omit the parameter });
And this will navigate to the polar sh payment page
final step webhook setup
Now we need to create an API route which will listen to webhook so that when payment is success we can get to know
Go to polar sh dashboard → settings → webhook → add endpoint that will be called by the webhook
format → raw (or whatever) select all or maybe as per you need and copy the webhookSecret
update .env
//.env.local POLAR_WEBHOOK_SECRET = polar_whs_your_webhook_secret
// src/app/api/webhook/polar/route.ts import { Webhooks } from "@polar-sh/nextjs"; export const POST = Webhooks({ webhookSecret: process.env.POLAR_WEBHOOK_SECRET!, onOrderPaid: async (payload: any) => { console.log("🎉 WEBHOOK TRIGGERED: onOrderPaid"); const customer = payload.data?.customer; try { await markUserAsPaid(customer.id) // or whatever logic you need to run }catch(error){ console.log('error in onOrderPaid',error); } } });
run the server
If you are in production use your domain else use ngrok in development
ngrok http 3000
//this will give you a URL like this https://4901-103-240-13-185.ngrok-free.app add your API route at end so the full will be https://4901-103-240-13-185.ngrok-free.app/api/webhook/polar https://your-domain.com/api/webhook/polar
test payment
Now when a user does the payment it will call your webhook which will call the function and your db is updated that's all you need to get your first paid user now build amazing stuff and get paid.
Last Note
I'm not a super Payment integration expert, its just personal experice and hope it helps you.
Useful Links
- polar.sh best way to integrate payment
- polar.sh x Nextjs Guide for nextjs
- support@polar.sh Support for polar.sh