The Click to Pay SDK is currently in Beta. To enable it for your merchant account, contact your Revolut account executive.
Enables customers to pay using Click to Pay, a card-network-based checkout experience backed by Visa and Mastercard. The SDK opens a pop-up widget where enrolled customers can complete their payment in just a few clicks - the card networks handle authentication and payment credential delivery behind the scenes. Customers can enter their card details during checkout through Click to Pay and opt in to save them to a new or existing Click to Pay profile for future use.
Key features:
- Card-network-backed checkout (Visa and Mastercard Click to Pay)
- Built-in 3DS authentication handled by the card networks
- No manual card entry for recognised or returning customers
- Optional billing address support
- Pop-up widget on your checkout page
For a complete implementation guide with examples, see: Accept payments via Click to Pay - Web
Check out our integration examples repository.
Prerequisites
This payment method requires payments module initialisation. See: Payments module initialisation
Click to Pay supports one-time card-not-present payments only. Merchant-initiated transactions (MIT) and recurring payments are not available. For subscription and recurring billing, consider SEPA Direct Debit or Revolut Pay.
Type signature
PaymentsInstance.clickToPay(
options: PaymentsModuleClickToPayOptions
): ClickToPayInstance
interface PaymentsModuleClickToPayOptions {
createOrder: () => Promise<{ publicId: string }>
billingAddress?: Address
onSuccess?: (payload: { orderId: string }) => void
onError?: (payload: {
error: RevolutCheckoutError
orderId: string
}) => void
onCancel?: (payload: { orderId: string | undefined }) => void
}
interface ClickToPayInstance {
show: () => void
destroy: () => void
}Parameters
| Parameter | Description | Type | Required |
|---|---|---|---|
options | Configuration object for Click to Pay | PaymentsModuleClickToPayOptions | Yes |
PaymentsModuleClickToPayOptions interface
| Parameter | Description | Type | Required |
|---|---|---|---|
createOrder | Async function that calls your backend to create an order and returns the order token | () => Promise<{publicId: string}> | Yes |
billingAddress | Provides the customer's billing address for payment processing and regulatory requirements. The SDK does not collect billing address — you must collect it on your frontend and pass it via this option. Accepts an Address object | Address | No |
onSuccess | Callback triggered when the payment has been authorised | (payload: {orderId: string}) => void | No |
onError | Callback triggered when the payment fails. Receives RevolutCheckoutError | (payload: {error: RevolutCheckoutError, orderId: string}) => void | No |
onCancel | Callback triggered when user cancels the payment. orderId may be undefined if order creation failed | (payload: {orderId?: string}) => void | No |
Return value
ClickToPayInstance
interface ClickToPayInstance {
show: () => void
destroy: () => void
}The method returns a ClickToPayInstance object containing:
| Method | Description | Type |
|---|---|---|
show | Open the Click to Pay pop-up widget | () => void |
destroy | Close the widget and clean up resources | () => void |
Callback events
The Click to Pay widget provides callback functions for handling payment lifecycle events.
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 }) => voidTriggered when the payment has been authorised. With automatic capture (default), the payment is captured immediately after. With manual capture, you capture the payment separately.
With automatic capture (default), authorisation and capture happen in quick succession. If you use manual capture, onSuccess fires after authorisation — you must capture the payment separately to complete the transaction.
Use cases:
- Display success message to the customer
- Redirect to order confirmation page
- Update UI to reflect successful payment
Example:
onSuccess: ({ orderId }) => {
console.log('Payment successful!', orderId)
window.location.href = `/confirmation?orderId=${orderId}`
}onError
(payload: { error: RevolutCheckoutError; orderId: string }) => voidTriggered 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
- Offer alternative payment methods
Example:
onError: ({ error, orderId }) => {
console.error('Payment failed:', error.message, orderId)
alert(`Payment failed: ${error.message}`)
}onCancel
(payload: { orderId: string | undefined }) => voidTriggered when the user cancels the payment. The orderId may be undefined if order creation failed or the user closed the widget before completing the flow.
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.')
}Usage examples
import RevolutCheckout from '@revolut/checkout'
// Initialise payments module
const { clickToPay } = await RevolutCheckout.payments({
publicToken: process.env.REVOLUT_PUBLIC_KEY,
mode: 'prod',
})
// Create Click to Pay instance
const instance = clickToPay({
createOrder: async () => {
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.')
},
})
// Show the widget when user clicks a button
document
.getElementById('click-to-pay-button')
.addEventListener('click', () => {
instance.show()
})With billing address provided
Provide the customer's billing address for payment processing and regulatory requirements:
const instance = clickToPay({
createOrder: async () => {
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 }
},
billingAddress: {
countryCode: 'GB',
region: 'London',
city: 'London',
streetLine1: '1 Revolut Street',
streetLine2: '',
postcode: 'EC2V 7HN',
},
onSuccess: ({ orderId }) => {
console.log('Payment successful!', orderId)
window.location.href = `/confirmation?orderId=${orderId}`
},
onError: ({ error, orderId }) => {
alert(`Payment failed: ${error.message}`)
},
})
document.getElementById('click-to-pay-button').addEventListener('click', () => {
instance.show()
})