Skip to content

@movmo/express-checkout-button

@movmo/express-checkout-button puts an “Express Checkout” button on a partner page. A click saves the selected flight offer to Movmo, then navigates the whole tab to Movmo’s checkout page; Movmo sends the traveler back to your returnUrl, where the SDK fires onBookingComplete and onExit. Payment, passengers and the airline booking call all happen on Movmo’s page, never on yours.

It ships in two forms; both render the same button and the same checkout:

  • A React component (MovmoCheckoutButton) for React 16.8+ apps.
  • A self-contained script tag for everything else: Vue, Angular, server-rendered templates, plain HTML. No build step, no framework, no npm install: the bundle carries React internally and injects its own styles.
Current version2.0.2
Peer dependenciesReact version — React 16.8+ (16.8 / 17 / 18). Script-tag version — none.
LicenseMIT
npm@movmo/express-checkout-button
CDN (script tag)https://cdn.e2e.movmo.io/sdk/express-checkout/v2/express-checkout.js

This page is the package reference. The build (where to mount it, the offer, the return, what travelers see) is the Express Checkout integration guide. Upgrading from 1.x: see the changelog.

Terminal window
npm install @movmo/express-checkout-button@^2.0.0

Import the package stylesheet once at app boot:

import "@movmo/express-checkout-button/dist/index.css";

The CSS does not include Tailwind’s preflight reset, so it will not interfere with your existing styles. It imports the Inter font from Google Fonts; override font-family if you serve fonts locally.

The package ships ESM and CommonJS builds behind an exports map (import, require, and ./dist/index.css) and imports cleanly during server-side rendering; the component acts on window only at mount and click time, so an ssr: false guard is optional.

Add one script tag and mount the button into any element:

<!-- No fixed height: the button renders at its natural size, about 303×68 px. -->
<div id="movmo-checkout-button"></div>
<script src="https://cdn.e2e.movmo.io/sdk/express-checkout/v2/express-checkout.js"></script>
<script>
MovmoExpressCheckout.mount("#movmo-checkout-button", {
iataCode: "PR",
apiKey: "YOUR_MOVMO_API_KEY",
providerID: "darwin",
flightOffer: selectedOffer,
});
</script>

The /v2/ URL is a mutable alias that tracks the latest 2.x release, which is why the example carries no integrity attribute (an SRI hash on it would break on the next release). If your security policy requires script-integrity verification, use the version-pinned + SRI form below instead.

The bundle is fully self-contained (about 54 KB gzipped): React is compiled in, and the button’s styles are injected at load — you do not need a <link> tag, a stylesheet import, or React on your page. If your page already runs React, the two copies do not interact; the button manages its own isolated root.

mount(target, options) takes a CSS selector or a DOM element, plus the same options as the React component’s props (below). It returns a handle:

const handle = MovmoExpressCheckout.mount(el, options);
handle.unmount(); // remove the button and clean up
MovmoExpressCheckout.version; // "2.0.2"

mount() validates its options at the call boundary and throws with a message naming exactly what is missing (apiKey, iataCode, providerID, and one of flightOffer/flightOfferID), and throws if the selector matches no element. Calling mount() a second time on the same element logs a warning and returns the existing handle instead of double-rendering.

MovmoExpressCheckout.consumeReturn(options) (ESM: consumeMovmoCheckoutReturn(options)) handles a return on a page that does not mount the button. It fires onBookingComplete, then onExit, when the return’s state nonce matches, scrubs only its own params (movmo_exit, movmo_state, movmo_booking_id, movmo_pnr, as of 2.0.1), and returns true when callbacks fired. Because it leaves every other movmo_* param alone, it can share a page with @movmo/connect-button, whose sign-out return (movmo_signed_out, movmo_logout_state) survives it. See Pages without the button.

MovmoExpressCheckout.consumeReturn({ isProd: true, onBookingComplete, onExit });

The /v2/ URL above tracks the latest 2.x release. If your security policy requires it (e.g. PCI DSS script-integrity controls), pin an exact version and verify it with SRI. Per-version bundles are immutable, and each release publishes its sha384 hash as a sidecar file next to the bundle: fetch https://cdn.e2e.movmo.io/sdk/express-checkout/{version}/express-checkout.js.sri (e.g. for 2.0.2) to get the exact integrity value:

<script
src="https://cdn.e2e.movmo.io/sdk/express-checkout/2.0.2/express-checkout.js"
integrity="sha384-XKBOkhiqyKEdN4HaO6ArVG3zO7AAPqhgAx95neP0VcMxBGlPrVN3JseLzFQeZ0NO"
crossorigin="anonymous"
></script>

An SRI-pinned tag does not auto-update — you take new releases by updating the URL and hash together.

PropTypeRequiredDescription
iataCodestringyesYour airline IATA code (e.g. "PR", "AA"). Sent to Movmo as movmo-customer-id; the checkout header shows the airline this code is registered to. Matched case-insensitively; onBookingComplete’s airlineRef echoes the value you passed.
apiKeystringyesYour Movmo API Gateway key. Sent as x-api-key. Provisioned at onboarding — see Authentication.
providerIDstringyesThe flight provider the offer came from: darwin, duffel, dohop, or the sandbox provider id Movmo issues at onboarding (e2e only) — see The offer object.
flightOfferobjectconditionalThe raw flight offer object from your provider. Required if flightOfferID is not set.
flightOfferIDstringconditionalThe Movmo offer UUID returned by a prior createProviderOffer call. Required if flightOffer is not set.
isProdbooleannotrue targets flights.movmo.io and api.movmo.io; false (default) targets flights.e2e.movmo.io and e2e.api.movmo.io.
classNamestringnoAppended to the button’s class list, for layout classes your own build compiles (e.g. a Tailwind w-full; the package CSS ships no width utilities of its own). React consumers — see Styling.
returnUrlstringnoWhere Movmo sends the traveler back to. Default: the page URL at click with every movmo_* query param removed; the fragment is kept only for router routes (#/, #!/). Must be https (http://localhost:3000 on e2e) on a registered origin, at most 2048 characters; otherwise there is no return link. It is sent to Movmo, so set it explicitly when your page URL carries tokens or personal data. See returnUrl.
onBookingComplete(info: { bookingId: string; airlinePnr?: string; airlineRef?: string; providerId?: string }) => voidnoCalled once on return from a confirmed booking, before onExit({ reason: "booking_confirmed" }). airlinePnr is the record locator in your reservation system. An unauthenticated browser signal: confirm server-side before fulfilling.
onExit(info: { reason: 'search_again' | 'offer_unavailable' | 'booking_confirmed' }) => voidnoCalled when the traveler returns from Movmo’s checkout, after onBookingComplete when both apply. Not called when the traveler presses back or closes the tab. See After the click.
onError(error: { stage: 'save_offer' | 'missing_offer'; status?: number; message: string }) => voidnoCalled when the click-time offer save fails or no offer was passed (the button never throws, and does not navigate) — see onError.

onBookingComplete and onExit fire on whichever page loads at returnUrl and mounts the button or calls consumeReturn. The mount() options are exactly these props.

Exactly one of flightOffer or flightOfferID must be set. The two props are mutually exclusive: pass the raw offer if you have not persisted it yet, or the saved offer ID if you already have. The script-tag mount() accepts exactly this options object.

Size and width only. The “Express Checkout” label, Movmo badge and colors are part of the checkout trust contract shown to travelers; do not restyle them.

#movmo-checkout-button button {
width: 100%;
}
  • Natural size is about 303×68 px. Never set a height; a container narrower than about 300 px wraps the label (the width depends on the page font).
  • React: pass a layout class via className (e.g. Tailwind w-full); your build compiles it.
  • Script tag: className only toggles classes inside the bundle’s own stylesheet, so use a descendant selector on your mount container as above.

The SDK calls one OpenAPI operation in raw-offer mode:

OperationPath
createProviderOfferPOST /v1/flights/providers/{provider}/offers

In flightOfferID mode (always the case for duffel), no REST call is made from the partner page; Movmo’s checkout page makes all subsequent calls itself. Full schemas in the OpenAPI spec under tags: [Flights].