Sandbox
Help

embeddedCheckout()

Mounts the Revolut Checkout widget to a DOM element, providing access to all enabled payment methods through a single, unified interface. The widget aggregates Revolut Pay, Card, Apple Pay, Google Pay, Pay by Bank, and other payment methods configured in your Business Dashboard.

Key features:

  • Unified widget for all payment methods
  • Dashboard-configured (no code changes to add/reorder methods)
  • Automatic payment method optimisation
  • Built-in customisation options

For a complete implementation guide with examples, see: Accept payments via Revolut Checkout - Web

Prerequisites

This payment method requires direct initialisation.

Type signature

RevolutCheckout.embeddedCheckout: (
  options: EmbeddedCheckoutOptions
) => Promise<EmbeddedCheckoutInstance>

interface EmbeddedCheckoutOptions {
  publicToken: string
  mode: 'prod' | 'sandbox'
  locale?: Locale | 'auto'
  target: HTMLElement
  createOrder: () => Promise<{ publicId: string }>
  revolutPayOptions?: EmbeddedCheckoutRevolutPayOptions
  onSuccess?: (payload: { orderId: string }) => void
  onError?: (payload: { error: RevolutCheckoutError; orderId: string }) => void
  onCancel?: (payload: { orderId: string | undefined }) => void
  email?: string
  billingAddress?: Address
  shippingOptions?: ShippingOption[]
  onShippingAddressChange?: (address: Address) => Promise<ShippingAddressChangeResult>
  onShippingOptionChange?: (option: ShippingOption) => Promise<ShippingChangeResult>
}

interface EmbeddedCheckoutRevolutPayOptions {
  mobileRedirectUrls?: {
    success: string
    failure: string
    cancel: string
  }
}

interface EmbeddedCheckoutInstance {
  destroy: () => void
}

Parameters

ParameterDescriptionTypeRequired
optionsConfiguration object for the embedded checkout widgetEmbeddedCheckoutOptionsYes

EmbeddedCheckoutOptions interface

ParameterDescriptionTypeRequired
publicTokenYour Merchant API Public keystringYes
modeAPI environment'prod' | 'sandbox'Yes
localeWidget languageLocale | 'auto' (default: 'auto')No
targetDOM element where the widget should be mountedHTMLElementYes
createOrderAsync function that calls your backend to create an order and returns the order token() => Promise<{publicId: string}>Yes
revolutPayOptionsConfiguration options specific to Revolut Pay within the embedded checkout widget. Required for Revolut Pay to be visible on mobile — see Revolut Pay options for details.EmbeddedCheckoutRevolutPayOptionsNo
onSuccessCallback triggered when payment completes successfully(payload: {orderId: string}) => voidNo
onErrorCallback triggered when payment fails. Receives RevolutCheckoutError(payload: {error: RevolutCheckoutError, orderId: string}) => voidNo
onCancelCallback triggered when user cancels payment. orderId may be undefined if order creation failed(payload: {orderId?: string}) => voidNo
emailProvide customer's email address. If provided, the email field is hidden from the checkout formstringNo
billingAddressProvide or skip the billing address form. If the provided address is valid, the billing form is hidden completely. If the address is invalid or incomplete, the form is shown with the pre-filled values. For the form to be hidden, countryCode, postcode, streetLine1, and city must be present and validAddressNo
shippingOptionsAvailable shipping options for the customerShippingOption[]No
onShippingAddressChangeCallback triggered when customer changes shipping address(address: Address) => Promise<ShippingAddressChangeResult>No
onShippingOptionChangeCallback triggered when customer selects a different shipping option(option: ShippingOption) => Promise<ShippingChangeResult>No

ShippingOption

interface ShippingOption {
  id: string
  label: string
  amount: number
  description?: string
}

Defines a shipping option available to the customer.

PropertyDescriptionTypeRequired
idUnique identifier for the shipping optionstringYes
labelDisplay name (e.g., "Standard Shipping")stringYes
amountShipping cost in lowest currency denominationnumberYes
descriptionAdditional details (e.g., "Delivery in 5-7 days")stringNo

ShippingChangeResult

type ShippingChangeResult = {
  status: 'success' | 'fail'
  total: {
    amount: number
    label?: string
  }
}

Response from onShippingOptionChange callback with updated total.

ShippingAddressChangeResult

type ShippingAddressChangeResult = {
  status: 'success' | 'fail'
  shippingOptions?: ShippingOption[]
  total: {
    amount: number
    label?: string
  }
}

Response from onShippingAddressChange callback with updated shipping options and total.

EmbeddedCheckoutRevolutPayOptions

Configuration options specific to Revolut Pay within the embedded checkout widget.

interface EmbeddedCheckoutRevolutPayOptions {
  mobileRedirectUrls?: {
    success: string
    failure: string
    cancel: string
  }
}
ParameterDescriptionTypeRequired
mobileRedirectUrlsAn object with URLs for redirecting the user after a Revolut Pay payment on mobile devices. See mobile redirect behaviour below.ObjectNo

Mobile redirect behaviour

On mobile devices, Revolut Pay needs to redirect the user out of the checkout flow and back once payment completes. mobileRedirectUrls configures the destination URLs for this redirect — one for each payment outcome:

  • success — URL the customer is redirected to after a successful payment
  • failure — URL the customer is redirected to after a failed payment
  • cancel — URL the customer is redirected to after cancelling the payment

Revolut Pay will not be displayed in the widget on mobile devices unless redirect targets are configured. You can provide them in one of two ways:

  • SDK-level: Set revolutPayOptions.mobileRedirectUrls in the embeddedCheckout() configuration (recommended for the embedded checkout widget)
  • API-level: Set redirect_url when creating the order via the Merchant API

If neither is configured, Revolut Pay will not appear as a payment method in the widget on mobile devices.

If the order was created with a redirect_url parameter (Merchant API), that value takes precedence over revolutPayOptions.mobileRedirectUrls and is used for all three outcomes (success, failure, cancel).

When a user is redirected, Revolut Pay appends the order's public ID (token) as a query parameter named _rp_oid to the URL. For example, for a success URL of https://example.com/success, the final URL will be: https://example.com/success?_rp_oid=fe34dbd3-3fa9-4d4c-8987-3f7735ba3cdf

You can retrieve this ID on your redirect page using the SDK's helper function:

import { getRevolutPayOrderIdURLParam } from '@revolut/checkout'

const revolutPublicOrderId = getRevolutPayOrderIdURLParam()

The _rp_oid query parameter and the redirect URL are untrusted client-side values. A user can forge or replay them. Do not treat arrival at the success URL as proof of payment.

To verify a payment:

  1. Send _rp_oid to your backend.
  2. Retrieve the order through the Merchant API: Retrieve an order endpoint.
  3. Only fulfil the order when the returned state is completed.

For critical backend actions such as order fulfilment, also use verified webhooks as the authoritative source of payment status.

For more details on redirect verification, see the Revolut Pay SDK reference.

Example:

const { destroy } = await RevolutCheckout.embeddedCheckout({
  publicToken: '<yourPublicApiKey>',
  mode: 'prod',
  target: document.getElementById('checkout-container'),

  createOrder: async () => {
    const order = await yourServerSideCall()
    return { publicId: order.token }
  },

  revolutPayOptions: {
    mobileRedirectUrls: {
      success: 'https://www.example.com/success',
      failure: 'https://www.example.com/failure',
      cancel: 'https://www.example.com/cancel',
    },
  },

  onSuccess: ({ orderId }) => {
    console.log('Payment successful!', orderId)
    window.location.href = `/confirmation?orderId=${orderId}`
  },

  onError: ({ error, orderId }) => {
    console.error('Payment failed:', error.message, orderId)
  },

  onCancel: ({ orderId }) => {
    console.log('Payment cancelled', orderId)
  },
})

Return value

Promise<EmbeddedCheckoutInstance>

interface EmbeddedCheckoutInstance {
  destroy: () => void
}

The promise resolves with an EmbeddedCheckoutInstance object containing:

PropertyDescriptionType
destroyFunction to remove the widget from the page and clean up resources() => void

Callback events

The embedded checkout widget provides the following callback functions for handling payment lifecycle events in your frontend.

Widget callbacks are not guaranteed to fire due to network issues, browser closures, or ad-blockers. Always use webhooks for critical backend operations like order fulfilment.

In all callbacks, orderId refers to the order's public token (order.token from the API response), not the internal order.id. This is the public identifier used in your frontend code.

onSuccess

(payload: { orderId: string }) => void

Triggered when the payment completes successfully.

Use cases:

  • Display success message to the customer
  • Redirect to order confirmation page
  • Update UI to reflect successful payment
  • Show success animations

Example:

onSuccess: ({ orderId }) => {
  console.log('Payment successful!', orderId)
  window.location.href = `/confirmation?orderId=${orderId}`
}

onError

(payload: { error: RevolutCheckoutError; orderId: string }) => void

Triggered when the payment fails. The error parameter is a RevolutCheckoutError object containing error details.

Use cases:

  • Display error message to the customer
  • Log error for debugging
  • Re-enable checkout form
  • Show retry option

Example:

onError: ({ error, orderId }) => {
  console.error('Payment failed:', error.message, orderId)
  alert(`Payment failed: ${error.message}`)
}

onCancel

(payload: { orderId: string | undefined }) => void

Triggered when the user cancels the payment. The orderId may be undefined if the order was not created yet.

Use cases:

  • Display cancellation message
  • Re-enable checkout form
  • Track abandonment analytics

Example:

onCancel: ({ orderId }) => {
  console.log('Payment cancelled', orderId)
  alert('Payment was cancelled. You can try again.')
}

onShippingAddressChange

(address: Address) => Promise<ShippingAddressChangeResult>

Triggered when the customer changes their shipping address. Validate the address and return updated shipping options and order total.

Use cases:

  • Validate delivery availability for the provided address
  • Update shipping options based on the customer's region
  • Recalculate order total with applicable shipping cost

Example:

const shippingOptions: ShippingOption[] = [
  { id: 'standard', label: 'Standard Shipping', amount: 500, description: 'Delivery in 5-7 days' },
  { id: 'express', label: 'Express Shipping', amount: 1000, description: 'Delivery in 1-2 days' }
]

const { destroy } = await RevolutCheckout.embeddedCheckout({
  // ... other configuration
  shippingOptions,
  onShippingAddressChange: async (address) => {
    const isValidRegion = await validateDeliveryRegion(address)

    if (!isValidRegion) {
      return {
        status: 'fail',
        total: { amount: 5000 }
      }
    }

    return {
      status: 'success',
      shippingOptions,
      total: { amount: 5000 + shippingOptions[0].amount }
    }
  }
})

onShippingOptionChange

(option: ShippingOption) => Promise<ShippingChangeResult>

Triggered when the customer selects a different shipping option. Return the updated order total.

Use cases:

  • Recalculate order total with the selected shipping cost
  • Update pricing display

Example:

onShippingOptionChange: async (selectedOption) => {
  return {
    status: 'success',
    total: {
      amount: 5000 + selectedOption.amount,
      label: 'Total'
    }
  }
}

Error handling

Throws: RevolutCheckoutError

The embedded checkout can throw errors in the following scenarios:

  • Invalid publicToken
  • Failed order creation in the createOrder callback
  • Network connectivity issues
  • Invalid configuration options
  • Widget loading failures

Example error handling:

try {
  const { destroy } = await RevolutCheckout.embeddedCheckout({
    // ... configuration
  })
} catch (error) {
  if (error.name === 'RevolutCheckout') {
    console.error('Checkout initialisation failed:', error.message)
    // Handle initialisation error
  }
}

For error handling within callbacks, see the onError callback section.

Usage example

import RevolutCheckout from '@revolut/checkout'

// Initialise and mount the embedded checkout
const { destroy } = await RevolutCheckout.embeddedCheckout({
  publicToken: process.env.REVOLUT_PUBLIC_KEY,
  mode: 'prod',
  locale: 'auto',
  target: document.getElementById('checkout-container'),

  createOrder: async () => {
    // Call your backend to create an order
    const response = await fetch('/api/create-order', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        amount: 1000,
        currency: 'GBP',
      }),
    })
    const order = await response.json()
    return { publicId: order.token }
  },

  onSuccess: ({ orderId }) => {
    console.log('Payment successful!', orderId)
    window.location.href = `/confirmation?orderId=${orderId}`
  },

  onError: ({ error, orderId }) => {
    console.error('Payment failed:', error.message, orderId)
    alert(`Payment failed: ${error.message}`)
  },

  onCancel: ({ orderId }) => {
    console.log('Payment cancelled', orderId)
    alert('Payment was cancelled.')
  },
})

// Later, if you need to remove the widget:
// destroy()

Provide customer information

You can improve the checkout experience by providing customer information upfront:

const { destroy } = await RevolutCheckout.embeddedCheckout({
  // ... other configuration
  email: 'customer@example.com',
  billingAddress: {
    countryCode: 'GB',
    region: 'Greater London',
    city: 'London',
    postcode: 'EC1A 1BB',
    streetLine1: '1 Example Street',
    streetLine2: 'Flat 2B',
  },
})

When you provide billingAddress, the widget applies the following behaviour:

  • Valid address - the billing address form is hidden completely. The customer does not need to enter or review any address fields.
  • Invalid or incomplete address - the billing address form is shown with the pre-filled values. The customer can review and correct any fields that failed validation.

For the form to be hidden, the widget pre-validates the address. The fields countryCode, postcode, streetLine1, and city must be present and valid. streetLine2 and region are not validated by the embedded checkout.

If email is provided — either in the widget configuration or on the order via the API — the email field is hidden from the checkout form.

See also

Rate this page