DEV Community

Cover image for I Spent Days Choosing Between Hosted Checkout, Embedded Checkout, and Custom Payment APIs — Here's What I Learned
Nadir Hussain
Nadir Hussain

Posted on

I Spent Days Choosing Between Hosted Checkout, Embedded Checkout, and Custom Payment APIs — Here's What I Learned

If you're integrating payments for the first time, don't make the same mistake I did.

The first payment integration I worked on wasn't difficult because of the code.

It was difficult because I had no idea which integration approach I should choose.

I opened the documentation for a payment provider expecting a simple guide. Instead, I was greeted with multiple options:

  • Hosted Checkout
  • Embedded Checkout
  • Payment Intents
  • Custom APIs
  • Webhooks
  • Client Secrets
  • Tokens
  • Sessions

As a beginner, I kept asking myself:

"Why are there so many ways to charge a customer?"

I wasn't confused by JavaScript.

I wasn't confused by APIs.

I was confused because every approach seemed capable of doing the exact same thing.

They all accepted payments.

So why did they all exist?

It wasn't until I worked on several real-world payment systems—from simple SaaS subscriptions to platforms supporting multiple payment providers—that everything finally clicked.

The biggest lesson I learned was this:

There is no "best" payment integration. There is only the right solution for your product.

If you're facing the same confusion today, this article will save you hours (or even days) of reading documentation.

Let's break it down.


The Three Ways to Accept Payments

Almost every modern payment provider offers one or more of these integration methods.

At first glance, they all accomplish the same goal:

Take money from a customer.

But they differ significantly in:

  • Security responsibilities
  • Development complexity
  • User experience
  • Customization
  • Maintenance
  • Scalability

Let's look at each one.


Option 1: Hosted Checkout

This is the simplest way to accept payments.

Instead of building a payment page yourself, you redirect the customer to a secure checkout page hosted by the payment provider.

What the Flow Looks Like

Your application creates a checkout session.

const session = await stripe.checkout.sessions.create({
  mode: "payment",
  line_items: [...],
  success_url: "...",
  cancel_url: "...",
});

return session.url;
Enter fullscreen mode Exit fullscreen mode

Then simply redirect the user.

window.location.href = session.url;
Enter fullscreen mode Exit fullscreen mode

That's it.

No card handling.

No PCI headaches.

No complex frontend.

The provider owns the checkout experience.

Why Companies Choose It

Hosted checkout is perfect when your priority is getting payments working quickly and securely.

The provider takes care of:

  • Card validation
  • 3D Secure authentication
  • Fraud prevention
  • PCI compliance
  • Security updates
  • Payment UI

Your job is simply to create the checkout session and listen for the result.

✅ Pros

  • Fastest implementation
  • Highest level of security
  • Minimal maintenance
  • Excellent for MVPs
  • Very reliable

❌ Cons

  • Customer leaves your website
  • Limited branding
  • Less control over the checkout experience

Option 2: Embedded Checkout

What if you want customers to stay on your website?

That's where embedded checkout comes in.

Instead of redirecting users, you embed the provider's secure payment form directly into your application.

Think of it like renting a secure payment form rather than building one yourself.

The user never leaves your application.

Yet the provider still securely handles sensitive payment information.

With Stripe Elements, for example:

<CardElement />

<Button onClick={handlePayment}>
  Pay Now
</Button>
Enter fullscreen mode Exit fullscreen mode

On the backend:

const paymentIntent = await stripe.paymentIntents.create({
  amount: 1000,
  currency: "usd",
});
Enter fullscreen mode Exit fullscreen mode

Then confirm the payment:

await stripe.confirmCardPayment(clientSecret, {
  payment_method: {
    card: elements.getElement(CardElement),
  },
});
Enter fullscreen mode Exit fullscreen mode

✅ Pros

  • Better user experience
  • Customers stay on your website
  • More customizable
  • Secure
  • Professional checkout experience

❌ Cons

  • More frontend work
  • More backend coordination
  • More payment state management

Option 3: Custom Payment APIs

This is the approach that fascinated me the most when I started.

I assumed:

"If large companies use custom APIs, then I should too."

That assumption was wrong.

Custom APIs give you complete control—but they also give you complete responsibility.

Instead of relying on hosted pages or embedded components, you build the entire payment experience yourself.

Your frontend sends a request to your backend:

await fetch("/api/payment", {
  method: "POST",
  body: JSON.stringify({
    amount: 5000,
    paymentMethodId,
  }),
});
Enter fullscreen mode Exit fullscreen mode

Your backend communicates with the payment provider:

const paymentIntent = await stripe.paymentIntents.create({
  amount,
  currency,
  payment_method,
  confirm: true,
});
Enter fullscreen mode Exit fullscreen mode

Looks simple...

Until reality kicks in.


The Hidden Complexity Nobody Talks About

Charging a customer is only a small part of building a payment system.

A production-ready payment platform usually includes:

  • Webhooks
  • Signature verification
  • Refund workflows
  • Subscription renewals
  • Retry logic
  • Failed payment recovery
  • Transaction history
  • Audit logs
  • Idempotency
  • Fraud detection
  • Analytics
  • Monitoring
  • Multiple payment providers

Most developers underestimate how much happens after the payment succeeds.


The Most Important Lesson I Learned

The payment page is not your payment system.

Your payment system is everything that happens before and after the customer clicks Pay.

This realization completely changed how I design payment architectures.


Which One Should You Choose?

Project Type Recommended Method
Portfolio Website Hosted Checkout
MVP Startup Hosted Checkout
SaaS Embedded Checkout
E-commerce Store Embedded Checkout
Marketplace Embedded + APIs
Wallet App Custom APIs
Banking App Custom APIs
Payment Platform Custom APIs

The goal isn't to use the most advanced solution.

The goal is to use the simplest solution that meets your business requirements.


Lessons I Wish Someone Had Told Me Earlier

1. Simplicity Wins

  • Don't build a custom checkout just because you can.
  • Build one only when your product genuinely needs it.

2. Security Is a Feature

  • Every line of payment code you own becomes your responsibility.
  • Sometimes less code is actually safer.

3. Never Trust the Frontend

  • Always verify payments using webhooks.
  • Never unlock premium features based only on a frontend success response.

4. Idempotency Is Essential

  • Users refresh pages.
  • Networks fail.
  • Browsers retry requests.
  • Your payment endpoint must safely handle duplicate requests.

5. Design for Failure

Always ask yourself:

  • What happens if the webhook is delivered twice?
  • What if the customer closes the browser?
  • What if payment succeeds but my database update fails?
  • What if the payment provider is temporarily unavailable?

Great payment systems are built around handling failures—not just successful payments.


Final Thoughts

Today, when I start integrating a payment gateway, I don't ask:

"Which API should I use?"

Instead, I ask:

"What experience do I want my users to have, and how much complexity is my team willing to own?"

That single question has helped me make better architectural decisions every time.

If you're just getting started with payments, begin with a hosted checkout. Understand how payment sessions, webhooks, and payment states work.

Once you're comfortable, move to embedded checkout for a better user experience.

Only choose custom APIs when your business requirements truly demand complete control.

The best payment integration isn't the most complex one.

It's the one that's secure, maintainable, and fits your product today while giving you room to grow tomorrow.


💬 I'd Love Your Thoughts

Which payment integration approach do you prefer?

  • Hosted Checkout
  • Embedded Checkout
  • Custom APIs
  • A combination of all three

Share your experience in the comments. I'd love to hear how you've approached payment architecture in your own projects.

Top comments (0)