actionRequired event lets your application intercept moments when the SDK is about to navigate the buyer away — either to a 3DS challenge page or to a generic payment-method redirect (voucher, bank handoff, etc.). You can take over presentation (open in a tab, render in your own modal, push a route) instead of letting the SDK mount its popup or call window.location.assign.
When the event fires
The SDK emitsactionRequired immediately before its default redirect/popup action, in these cases:
If no listener is attached — or if attached listeners do not call
preventDefault() — the SDK handles the user flow: it mounts a popup (or redirects, depending on the config).
Subscribing
on() returns an unsubscribe function. There is also payrails.off(name, handler) if you need to remove a specific handler.
Lifetime note
Payrails.init resets all registered listeners. Subscribe after awaiting Payrails.init, and re-subscribe if you re-init.Three integration patterns
1. Observe only — don’t change behavior
Subscribe without callingpreventDefault. Useful for analytics, logging, or showing your own toast before the popup opens.
2. Open the action URL in a new tab
For merchants who don’t want the buyer to leave the checkout page.3. Render the URL inside your own modal / SPA route
async — the SDK awaits each one before deciding whether to fall back to its default action. preventDefault() only needs to be called synchronously if you want to suppress the default; calling it later in an await chain still works as long as it happens before your handler resolves.
Handler contract & gotchas
preventDefault()is sticky. Once called by any handler, the SDK skips its default action for that emission. Other handlers still run.- Errors thrown inside handlers are caught. They are logged via
PayrailsLogger.errorand do not prevent other handlers from running, nor do they implicitly callpreventDefault. If a handler throws, the SDK will still perform its default action unless another handler suppressed it. executionIdties back to the Payrails workflow execution — use this to correlate with backend polling or webhooks.
UI state when you intercept
When you callpreventDefault(), the SDK considers its UI obligation discharged. Concretely, in the current release the CardPaymentButton loading spinner is not automatically reset after interception.
Unsubscribing
useEffect cleanup, Vue onUnmounted, etc.) to avoid double-firing if the host component remounts.