Skip to main content
By default, a checkout link sends the customer to a Kelviq-hosted page. With the @kelviq/js-checkout SDK you can keep the customer on your site instead: open checkout as a modal overlay over your current page, or mount it inline inside your own layout. The SDK reports the checkout lifecycle (loaded, success, close, error) back to callbacks you provide. It is a small script with no dependencies. It works with plain HTML and with any framework.
Embedded checkout needs a checkout session URL created with the Checkout API. Static /buy/ links are not supported in embedded mode yet.

1. Install the SDK

The package ships ESM and TypeScript types. The examples below use the Kelviq global; with npm, call open() and embed() directly instead.

2. Create a checkout session

Create the session from your backend with your server API key and pass the returned checkoutUrl to the browser. The same call accepts a customer, discount code, metadata, and the other options described in Create a checkout session.
Leave successUrl out of sessions you open with kelviq.js if you want the onSuccess callback. A session with a successUrl redirects your whole page to that URL when payment completes, and onSuccess never fires. See Success callback or redirect.
Pass the checkoutUrl to the browser exactly as returned. Do not rewrite its host: the script only accepts messages from the origin of the URL you give it.

3. Open checkout

Open checkout as a modal over the current page. Good for a Buy button anywhere on your site.
Kelviq.open() returns a handle with close(). The overlay also closes when the customer clicks the × button, presses Escape, or clicks the backdrop.

Options

Both methods take url, the optional theme, and the callbacks below. Kelviq.open() also accepts the overlay options.

Color mode (theme)

Pass the mode your page is currently showing. When you omit it, the Default mode configured in the dashboard applies. The checkout’s own light/dark switcher is hidden whenever it is embedded; your page decides.

Callbacks

onClose does not fire when the checkout is about to redirect your page (see below). Use onError to recover, for example by creating a fresh session and opening it again.

Overlay options (Kelviq.open only)

The modal never exceeds the viewport: width and height are capped at the viewport size minus a 24px margin on each side. On phones (viewports up to 519px wide) it opens as a full-screen sheet instead.

Handles

Opening a second overlay closes the first one. Calling close() or destroy() twice is safe.

Change the plan from your page (update)

update({ planIdentifier?, chargePeriod? }) switches the plan or billing period of the running checkout in place, without reloading it or losing what the customer typed. Use it when your own page has the pricing controls, for example a monthly/yearly toggle next to an inline checkout. Requires @kelviq/js-checkout 1.1.0 or later.
  • Values must exist on the session: a plan from the offering and one of its enabled billing periods. The checkout ignores anything else.
  • If you change only the period and the current plan has no price for it, the checkout picks the first plan that does, as its own period tabs do.
  • Calls made before onLoaded are queued and applied once the checkout has loaded.
  • To hide the checkout’s own plan selector and keep yours as the single source of truth, create the session with plansEnabled: false.

Use with a framework

Call the SDK only in the browser, after the component has mounted, and clean up with the handle when the component unmounts. Never call it during server rendering.
In Next.js, mark the component with 'use client'. The url comes from a server action or route handler that calls the Checkout API with your server API key.

Success callback or redirect

A checkout session ends in exactly one of two ways, decided by whether it has a successUrl: If you rely on onSuccess for analytics or to update your UI, create the session without a successUrl. For fulfilment, use the checkout.completed webhook in either case: a browser callback can be missed if the customer closes the tab.

Sandbox

Sessions created with a sandbox server API key return a sandbox checkoutUrl. Pass it to kelviq.js the same way; the script works with both environments. Use a test card (for example 4242 4242 4242 4242) to complete a test payment. See Sandbox and Test payments.

Browser support

  • Your page (the SDK): every browser Stripe.js supports, including Chrome 38+, Safari 10.1+, Firefox 29+, Edge 15+, iOS Safari 9+ and Android Chrome 38+. The script never breaks the host page on an unsupported browser.
  • The checkout inside the frame: Chrome and Edge 99+, Firefox 97+, Safari 15.4+. On older browsers the customer sees a “browser not supported” message instead of the form, and onClose still fires if they dismiss it.

Limitations

  • Static checkout links (https://www.kelviq.com/buy/…) cannot be embedded yet. Create a session with the Checkout API and embed its checkoutUrl.
  • Redirect-based payment methods such as iDEAL and Bancontact are not supported in embedded mode. Card payments, including 3D Secure challenges, work.
  • Kelviq controls which sites may frame the checkout. If your embed renders blank and the browser console reports a frame-ancestors violation, contact hi@kelviq.com with the domain you embed from.

Troubleshooting

Check the browser console. A Content-Security-Policy frame-ancestors error means the page is not allowed to frame Kelviq Checkout from your domain. A 404 inside the frame means the session ID is wrong or the session has expired.
The session was created with a successUrl, so the page redirected instead. Create the session without a successUrl, or handle the redirect landing page on your side.
The session has expired, was already used, or could not be loaded. onError fires with a code such as ERR_SESSION_EXPIRED; create a new session and open it again.
Make sure you passed the checkoutUrl exactly as the API returned it. The script ignores messages from any other origin, including a different subdomain of the same host.