Embedded Fields — embedded payment fields
Drop Embedded Fields into your checkout and your buyer's card information flows directly to the gateway — never touching your server, never landing in your DOM. The card iframe sits inside your form: you have full branding control of your page — everything outside the iframe — and theme-level control inside it (font + color) to match your look. The card data reflects straight through to the processor; we keep you out of PCI scope. In the default embed mode the card is one combined box — number, expiry, and CVC together, with font + color theming only inside; in elements mode you can keep that combined box or split it into the three discrete card-number / card-expiry / card-cvc fields. For control over where the card and the other input fields (email, cardholder, billing address) sit on your page, mount them as discrete Elements.
Two render modes: embed vs elements
Embedded Fields renders in one of two modes, set per session via integrationMode (default embed, no account-wide setting):
embed(default) — one combined card box renders the whole payment surface (card + cardholder, billing address, eligible Apple Pay / Google Pay, and a returning buyer's saved cards). You place onlyemailandsave-for-future-use.elements— you place the card, email, cardholder, address, and other pieces as discrete elements, where your account supports it; the card can stay the combined box or split into the three discretecard-number/card-expiry/card-cvcfields. Unsupportedelementssessions fall back toembedsilently (never an error).
→ Render modes: embed vs elements is the full model — capability matrix, fallback, what each mode means. Build a custom checkout covers setting integrationMode and branching on the echoed value.
This is the embedded path (either mode); the alternative is hosted checkout, where the buyer redirects to checkout.vonpay.com. Hosted is fastest to integrate; Embedded Fields keeps buyers on your domain with full control over the page.
Pages in this section
- Quickstart — end-to-end card-only integration in ~10 minutes
- Build a custom checkout — opt a session into discrete
elementsrendering withintegrationMode, plus the fallback-to-embedbehavior - Customize the look & feel — interactive playground, three reference themes, the style allowlist, and what's stylable vs not
- Render modes: embed vs elements — the one canonical explainer for the two render modes (
embedmonolith vs composableelements), the per-binder capability matrix, and the silent fallback - Element reference — Card, Email, Save-for-future-use, discrete card fields; Apple Pay & Google Pay render automatically inside the card mount when the buyer's device and your domain are eligible. Returning buyers' saved cards already appear inside the embed when you set a buyer on the session; the discrete saved-methods element (elements mode) is not usable yet.
- Using React —
<VoraProvider>,<CardField>,useVora()patterns + the imperative elements API - Tokenization & charge-and-save — the two submit flows: tokenize-only (charge later via Payment Intents) and charge-and-save (charges on submit, optionally vaults a reusable method); the
{ charged: true }result, buyer-vs-guest split, and confirm-via-webhook rule - Error handling —
VoraMirrorErrorcodes and recovery - 3D Secure — modal harmonization,
disable3dsModalopt-out,confirmPaymentIntent+handleActionflows, test cards
Working sample
samples/frame-react in the SDK repo is the canonical end-to-end reference — Express server stub for /api/create-session plus a React app using @vonpay/vora-react. Clone, fill in .env, pnpm dev.
Server-side reference
The server-side payment lifecycle (/v1/payment_intents, capture, refund, void, MIT, webhooks) is shared with the hosted-checkout flow.
The same
submit()either tokenizes or charges — that's a property of the session you created, not an account setting, and you choose it per session.
- Tokenize-only: create a no-charge (setup) session.
submit()returns avp_pmt_*token and charges nothing. You charge it server-side later with Payment Intents.- Charge-and-save: create a payment session (with an amount).
submit()charges the card on submit and, when a buyer is attached to the session, also vaults a reusablevp_pmt_*in the same step. Do not call/v1/payment_intentsfor that session — it would double-charge. See Charge-and-save.⚠️ Read the result, not your account config. The submit result is a discriminated union — branch
error→token→charged:
{ token: "vp_pmt_..." }on a tokenize-only session is an uncharged token to charge later; on a charge-and-save session it's already charged and reusable.{ charged: true }(no token) is a guest charge-and-save — charged once, saved nothing.{ error }means nothing was charged.Because the same token shape means "charge later" on a setup session and "already charged" on a payment session, branch on which session you created — but that's your own per-session choice, not an account mode. Either way the client result is only a UX signal — confirm settlement via the webhook before fulfilling (never mark the order failed on a client error, and never resubmit blindly — see Reconciliation for the duplicate-safe pattern). See Charge-and-save for the full result contract.