Skip to main content

Checkout SDK

The NetValve Checkout SDK is a small JavaScript library you load on your checkout page. You give it a payment session and a place to render, and it draws the entire payment UI — card fields and alternative payment methods (APMs) — and drives the payment to completion. Card encryption, the sale call, 3-D Secure challenges, APM redirects, and status polling are all handled inside the SDK. You do not build a card form, call the encrypt endpoint, or talk to the payment API from the browser yourself.

This page is the client-side integration how-to. The raw HTTP contracts the SDK uses under the hood (/sdk/initializeSession, /hpf/encryptField, /sdk/sale, /sdk/3ds/payment, /sdk/inquiry) are part of the Payment API — see the Payment API Integration guide and the API reference for those contracts.

PCI scope

Customers type their card details into NetValve-hosted iframes. The card number and CVV never touch your page or your server, so your PCI footprint stays minimal. Never build your own card form or POST card data — let the SDK render the hosted fields.

How it fits together​

End-to-end flow:

  1. Your server calls POST /sdk/initializeSession with your API credentials and gets back a session (a paymentToken, a jwtToken, the SDK script URL, and your site's payment-page layout).
  2. Your server returns that session to the browser.
  3. The browser loads the SDK script from session.netvalveScriptSrc.
  4. NetvalveSDK.init(session) renders the checkout — only the payment methods your site enables.
  5. The customer pays. The SDK encrypts the card fields, calls /sdk/sale, runs any 3DS challenge, and polls APM status for you.
  6. On a terminal result the SDK either redirects to your success / cancel / failed URLs, or calls your onComplete / onFail callbacks — your choice.

Before you start​

  • A NetValve site ID and API credentials (used only on your server to create sessions — never expose them in the browser).
  • Your payment methods (cards, Apple Pay, Google Pay, PIX, PSE, Volt, PayPal, Venmo, SPEI, Bitpace, Sezzle) enabled on your site. The SDK renders whatever your site's layout allows; you do not select methods in code.
  • Success, cancel, and failed URLs on your site for the post-payment handoff.
  • A Content-Security-Policy that allows the NetValve SDK, hosted-fields, and payment-API hosts (see Security & CSP below).
info

Contact the NetValve team to ensure your site is provisioned and you have credentials for API authentication.

Hosts are self-describing. The session response carries an endpoints block (apiBaseUrl, tokenfieldUrl, scriptSrc) for the environment it was minted against. The SDK reads the payment-API and hosted-field hosts from it — you never hardcode environment hostnames in your page.

Step 1 — Create a payment session (server-side)​

From your backend, create a session for the order. Do this on the server so your API key stays secret. Return the full response to the browser unchanged.

POST {{paymentApiUrl}}/sdk/initializeSession
netvalve-api-key: YOUR_API_KEY
netvalve-client-id: YOUR_CLIENT_ID
Content-Type: application/json

{
"amount": 44.00,
"currency": "BRL",
"siteId": "71c4fdd9-dc7d-47f4-8beb-cd232bbccadb",
"clientOrderId": "ORDER_12345",
"orderDesc": "Order #12345",
"successUrl": "https://shop.example.com/success",
"cancelUrl": "https://shop.example.com/cart",
"failedUrl": "https://shop.example.com/failed"
}

Send this to your NetValve payment-API domain ({{paymentApiUrl}} from onboarding) and authenticate it with your netvalve-api-key and netvalve-client-id headers — this is the only call that uses your secret credentials, which is why it must run server-side. The SDK then makes every other call under the hood — /hpf/encryptField, /sdk/sale, /sdk/3ds/payment, /sdk/inquiry — authenticating with the session's jwtToken as a Bearer token. You never handle that token yourself.

For an APM-first checkout (starting the session already on a specific APM, e.g. PIX), also send paymentOption (e.g. apm_pix) and alternativePaymentMethod (the customer's document data: userType, documentType, documentNumber, etc.) in this request. The allowed values and field shapes are owned by the Initialize SDK session. If you skip alternativePaymentMethod, the SDK collects the identity itself at payment time — for PIX it renders an inline name + CPF/CNPJ form and enables the pay button only once the details are valid; other APMs render whatever identity fields your gateway configuration defines.

The response includes everything the SDK needs: netvalveScriptSrc (the script URL), version and integrity (SDK bundle SRI hash), paymentToken, jwtToken, the endpoints block (host URLs), and initConfig (your site layout, order details, and redirect URLs).See the Initialize SDK session for the full response shape.

tip

Pass the entire session response to the browser and into init() as-is. Do not strip or rename fields — the SDK reads layout, tokens, and redirect URLs from it.

Step 2 — Load the SDK on your checkout page​

Add a container element where the checkout should render:

<!-- somewhere on your checkout page -->
<div id="nv-checkout"></div>

Then inject the SDK script using the URL from the session. Use it exactly as returned and set crossOrigin="anonymous".

// `session` is the object your server got from /sdk/initializeSession
const script = document.createElement("script");
script.src = session.netvalveScriptSrc; // signed URL — use exactly as returned
script.crossOrigin = "anonymous";
// Optional hardening: pin the bundle with the SRI hash from the session.
// script.integrity = session.integrity;
script.onload = () => mountCheckout(session);
script.onerror = () => showError("Could not load the payment form.");
document.head.appendChild(script);

When the script loads it registers a global: window.NetvalveSDK.

Step 3 — Initialize the SDK​

Call NetvalveSDK.init() with the session, a container, and your callbacks. It returns an instance you can later tear down with destroy().

function mountCheckout(session) {
const sdk = window.NetvalveSDK.init({
...session, // pass the whole initializeSession response through
container: "#nv-checkout", // CSS selector or an HTMLElement
autoRedirect: true, // SDK navigates to your success/cancel/failed URLs

onComplete: (event) => {
// payment approved — event.payload holds the transaction result
},
onFail: (event) => {
// payment declined or errored
},
});

return sdk;
}

init() options​

OptionTypeRequiredDescription
containerstring | HTMLElementYesCSS selector or DOM node the SDK renders into. Must exist before init().
autoRedirectbooleanNo (default true)When true, the SDK navigates the browser to successUrl / cancelUrl / failedUrl on a terminal result, and opens APM provider redirects itself. Set false to handle navigation yourself in callbacks. (See Embedded mode)
themeobjectNoBrand tokens (colors, radii, font) applied to the checkout. (See Theming & layout).
layoutobjectNoMethod order and presentation overrides. (See Theming & layout)
onCompletefunction(SdkEvent)No*Called once when the payment is approved.
onFailfunction(SdkEvent)No*Called once when the payment is declined or errors.
onEventfunction(SdkEvent)NoCalled for every event (ready, pending, complete, fail, cancel). Required in embedded mode to drive APM redirects (see Step 4).
...sessionobjectYesThe spread initializeSession response — supplies paymentToken, jwtToken, netvalveScriptSrc, endpoints , initConfig, and the redirect URLs.

* onComplete / onFail are optional in redirect mode (the SDK navigates for you) but required in embedded mode (autoRedirect: false).

Step 4 — Handle the result​

Choose one of two modes.

Redirect mode (default). Set autoRedirect: true and provide successUrl / cancelUrl / failedUrl in the session. The SDK sends the browser to the right URL when the payment finishes, and opens any APM provider redirect (PSE, Volt, Bitpace, Sezzle) itself. On success and failure it appends ?transactionID=…. You do not need callbacks.

Embedded mode. Set autoRedirect: false and implement onComplete / onFail. The SDK stays put and hands you the result so your app controls navigation (ideal for SPAs). In this mode you are responsible for opening APM provider redirects — handle the pending event (see below).

const sdk = window.NetvalveSDK.init({
...session,
container: document.getElementById("nv-checkout"),
autoRedirect: false, // you handle navigation

onComplete: (event) => {
const txId = event.payload?.transactionID;
window.location.assign(`/order/confirmed?tx=${txId}`);
},
onFail: (event) => {
window.location.assign(`/order/failed`);
},
onEvent: (event) => {
// Redirect APMs (PSE / Volt / Bitpace / Sezzle) surface their provider URL
// on a non-terminal "pending" event. In embedded mode YOU must open it.
// (PIX/SPEI "pending" carry no apmPaymentUrl — the SDK shows the QR/voucher
// and polls itself, so this safely no-ops for them.)
if (event.type === "pending") {
const url = event.payload?.apmPaymentInfo?.apmPaymentUrl;
if (url) window.location.assign(url);
}
},
});

The SdkEvent object​

FieldTypeDescription
typestring"ready" | "pending" | "complete" | "fail" | "cancel"
methodstring | nullWhich method produced it: "card" | "wallet" | "pix" | "pse" | "volt" | "paypal" | "venmo" | "spei" | "bitpace" | "sezzle" | "system"
payloadobjectThe transaction result (see below). Empty for ready.
atstringISO-8601 timestamp.

complete, fail, and cancel are terminal (the SDK shows its result screen and, in redirect mode, navigates). pending is non-terminal — an APM handed back a next step (a provider redirect URL, or a PIX QR / SPEI voucher the SDK is now displaying and polling).

Key fields on event.payload​

FieldMeaning
transactionIDNetValve transaction id. Appended to successUrl / failedUrl as ?transactionID= in redirect mode.
responseCodeTypeAPPROVED | PENDING | SOFT DECLINE | DECLINED | HARD_DECLINE | ERROR
orderStatePAID | PENDING | AWAIT_3DS | DECLINED | EXPIRED | CANCELED
responseMessageHuman-readable status to surface in your UI.
apmPaymentInfo.apmPaymentUrlOn a redirect-APM pending event — the provider page to send the customer to (embedded mode only; redirect mode opens it for you).

Alternative: native DOM events​

If callbacks don't suit your stack, the SDK also dispatches custom events on the container element:

const el = document.getElementById("nv-checkout");
el.addEventListener("nv-payment-complete", (e) => {
const event = e.detail; // an SdkEvent
});
el.addEventListener("nv-payment-fail", (e) => { /* ... */ });
el.addEventListener("nv-payment-cancel", (e) => { /* ... */ });
el.addEventListener("nv-payment-pending", (e) => { /* ... */ });
el.addEventListener("nv-payment-ready", (e) => { /* ... */ });

Payment methods​

Methods are enabled per-site in your NetValve configuration (allowedPaymentOptions in the site's payment-page layout). The SDK renders whatever your site allows — you write no per-method code.

MethodSite option (allowedPaymentOptions)What the customer sees
Cards (Visa / Mastercard / Amex / …)VISA, MASTERCARD, AMEX, DISCOVER, DINERS, JCBHosted, PCI-safe card fields plus a cardholder-name field. 3-D Secure runs automatically inside the SDK when the issuer requires it.
Apple PayAPPLEPAYThe Apple Pay button, shown only on devices and browsers that support Apple Pay. The customer approves in the Apple Pay sheet and the payment completes without leaving the page. Needs one-time domain setup, see Apple Pay and Google Pay.
Google PayGOOGLEPAYThe Google Pay button, shown only when Google Pay reports the customer can pay. The customer approves in the Google Pay sheet and the payment completes without leaving the page.
PIXPIXThe SDK collects the customer's name and CPF/CNPJ (skipped when the session already carries alternativePaymentMethod), then shows a QR code and polls until the bank confirms payment.
PSEPSECustomer picks their bank and fills the required identity fields, then is redirected to the bank and back to your URLs.
Volt (open banking)VOLTCustomer selects country, then bank, then is redirected to authorise and back. Needs the order currency.
PayPalPAYPALPayPal's hosted button (via Braintree); tokenises and completes without leaving the page.
VenmoVENMONative Venmo button (via Braintree); tokenises and completes without leaving the page.
SPEISPEIBank-transfer instructions (CLABE / reference); the SDK polls until the transfer clears.
BitpaceBITPACERedirect to the Bitpace crypto-payment page, then back to your URLs.
SezzleSEZZLERedirect to Sezzle's buy-now-pay-later flow, then back to your URLs.

Redirect APMs — PSE, Volt, Bitpace, and Sezzle send the customer to a provider page. In redirect mode (autoRedirect: true) the SDK opens it; in embedded mode you open it from the pending event (see Step 4). PayPal and Venmo normally complete in place, but the gateway can occasionally hand back a provider redirect as well — it flows through the same pending event, so the embedded-mode handler in Step 4 already covers it.

Apple Pay and Google Pay​

The SDK runs the whole wallet flow for you: it renders the button, opens the Apple Pay or Google Pay sheet, validates the session with NetValve, and submits the wallet token on /sdk/sale. Wallet results arrive on the same complete / fail events as cards, with method: "wallet". NetValve holds the wallet certificates and decrypts the token server-side, so there are no keys or certificates on your side (see the Digital Wallets overview).

What you need to do:

  1. Enable the wallet on your site. Ask the NetValve team to add APPLEPAY and/or GOOGLEPAY to your site's allowedPaymentOptions.
  2. Apple Pay only: register your checkout domain. Apple Pay validates against the hostname of the page the SDK runs on (window.location.hostname), so that exact domain must be registered with NetValve and serve Apple's domain-association file. Register every hostname customers check out on (apex, www, subdomains), in both sandbox and production. See Setting up Apple Pay on your domains.
  3. Google Pay only: allow Google's script. The SDK loads Google's pay.js from https://pay.google.com, so add that host to your CSP (see Security & CSP). There is no per-domain registration with NetValve; the SDK fills in the gateway parameters from your site.

Good to know:

  • The card networks offered in the wallet sheet follow the card brands enabled on your site (VISA, MASTERCARD, AMEX, DISCOVER, JCB). If none are enabled, the sheet offers Visa and Mastercard.
  • A wallet button that cannot be used on the customer's device is not shown at all, so do not expect to see Apple Pay in Chrome or on most Android devices.
  • Google Pay runs in Google's TEST environment on sandbox and PRODUCTION on live, picked automatically from the session's payment-API host.

Theming & layout​

Restyle the checkout and re-order the payment methods with two optional init() options: theme (colors, corner radii, font) and layout (method order, presentation, header/footer). Both are typed options you pass from your own code — no raw CSS editing, no backend change, no separate build.

window.NetvalveSDK.init({
...session,
container: "#nv-checkout",
theme: {
accent: "#7c3aed", // buttons, active borders, focus
radiusMd: "12px",
radiusLg: "16px",
fontSans: "Inter, system-ui, sans-serif",
},
layout: {
order: ["card", "pix", "paypal"], // methods you want first
listMode: "accordion", // single-open rows
showFooter: false, // hide the footer
},
});

Both objects are fully optional, and so is every field inside them. Supply a subset; anything you omit keeps its NetValve default. An init() with neither option renders exactly as it did before this feature existed.

Theme tokens​

Each token maps to one style in the checkout. Pass any CSS-valid string — a hex color, rgba(), a length, a font stack.

TokenPurposeDefault
accentPrimary accent: buttons, active borders, focus#4cc2ff
accentDarkDark accent: text on accent, method titles#112631
accentStrongStronger accent for hover / pressed. Auto-derived from accent when omitted#21abf2
surfaceRaisedCards, modal, hosted-field box#ffffff
textPrimaryPrimary body text#131313
textSecondarySecondary / label text#6b7280
textTertiaryTertiary / placeholder text#9ca3af
textLinkHyperlinks#185fa5
borderSubtleSubtle borders / dividers#dedede
inputBorderForm input borders#d1d1d1
errorError text / border#c32c34
errorRingError focus ringrgba(195, 44, 52, 0.25)
focusRingAccent focus ringrgba(76, 194, 255, 0.3)
successSuccess text / icons#008000
gray100Light gray fill#f3f4f6
gray700Dark gray text#374151
radiusMdMedium corner radius: inputs, buttons8px
radiusLgLarge corner radius: cards, modal12px
fontSansSans-serif font stacksystem UI stack

Hover follows your accent​

Setting accent alone is enough. The SDK derives the Pay button's hover background (your accent darkened ~15%) and its hover glow from it, so hover stays on-brand instead of falling back to NetValve blue. Set accentStrong yourself to override the derived shade.

Derivation needs a hex accent (#rgb or #rrggbb). If you pass rgba(), hsl(), or a named color, the SDK skips derivation rather than mis-parse it — supply accentStrong explicitly in that case.

Card fields are themed too​

The card number / expiry / CVV inputs live inside a cross-origin NetValve iframe, which cannot inherit your page's styles. The SDK bridges this for you: it derives the iframe's text color, placeholder color, invalid color, and font from textPrimary, textTertiary, error, and fontSans and passes them in. You theme the hosted fields with the same tokens — there is no extra step.

Layout overrides​

OptionTypeEffect
orderarray of method keysRender order for the payment methods.
listMode"list" | "accordion"Presentation of the method list.
showHeaderbooleanForce the header visible (true) or hidden (false).
showFooterbooleanForce the footer visible (true) or hidden (false).

order — listed keys lead, in the order you give them; any method you don't list keeps its default relative order and follows after. Unknown keys are ignored, so a shared config can safely name methods a given site doesn't enable.

layout: { order: ["pix", "card"] } // PIX first, cards second, the rest follow

Valid keys: card, pix, pse, volt, bitpace, spei, sezzle, paypal, venmo, applepay, googlepay.

listMode — "list" (default) renders every method expanded and stacked. "accordion" collapses them into single-open rows: the first is open, and opening one closes the others. Useful when you enable many methods.

showHeader / showFooter — three-state. true forces visible, false forces hidden, and omitting the field defers to your site's configured layout flags — the default. When the footer is visible it renders the footer lines configured on your site; with none configured it falls back to "Powered by Netvalve".

note

Ordering and header/footer overrides only affect presentation. Which methods exist is still driven entirely by your site's allowedPaymentOptions — order cannot add a method your site does not enable.

What wins when​

Styling can arrive from three places. Precedence is per-property, highest first:

  1. init({ theme }) — the tokens you pass in code.

  2. Your site's configured stylesheet — the CSS attached to your NetValve site configuration.

  3. NetValve defaults.

So a token you pass to init() always beats the portal-configured stylesheet for that one property, and a token you omit falls through to the next layer down. A partial theme never breaks the rest of the UI — only the tokens you supply are applied.

For finer, per-method styling that tokens don't cover, use the stylesheet configured on your site; the token API is deliberately global to the checkout.

Cleaning up​

When you remove the checkout (route change, modal close), tear the SDK down. This stops every payment method, removes listeners, and clears the container.

sdk.destroy();

Security & CSP​

  • Serve your checkout page over HTTPS. Hosted fields require a secure context.
  • Keep API credentials server-side only. Only the POST /sdk/initializeSession call uses them (netvalve-api-key + netvalve-client-id headers). The browser only ever sees the session — a short-lived paymentToken + jwtToken; the SDK uses that jwtToken as the Bearer credential for its own under-the-hood calls.
  • Never log or store the raw card number, CVV, or the tokens.
  • The session's endpoints block names the three hosts to allow: the SDK bundle host (scriptSrc origin), the hosted card-field host (tokenfieldUrl — the card iframes), and the payment-API host (apiBaseUrl — every /sdk/* and /hpf/* call).
  • Allow those hosts in your Content-Security-Policy:
Content-Security-Policy:
script-src 'self' https://sdk.YOUR-ENV.netvalve.com; # the SDK bundle (scriptSrc origin)
frame-src https://tokenfield.YOUR-ENV.netvalve.com; # hosted card fields (tokenfieldUrl)
connect-src https://payment-api.YOUR-ENV.netvalve.com; # payment API (apiBaseUrl): initializeSession / encryptField / sale / 3DS / inquiry

If you enable Google Pay, also allow https://pay.google.com in script-src, frame-src and connect-src (Google's pay.js and its payment sheet). Apple Pay needs no extra CSP entries: the Apple Pay sheet is native to the browser.

Replace YOUR-ENV with the hosts from the session's endpoints block (they differ per environment).

If you set fontSans to a web font your page loads from another origin, allow that origin in your font-src / style-src too — the SDK only names the font, it does not load it for you.

Troubleshooting​

SymptomLikely cause / fix
SDK script fails to load / window.NetvalveSDK undefinedUse the exact netvalveScriptSrc from the session. Check script-src in your CSP and that you waited for script.onload.
Checkout renders but card fields are blankYour CSP frame-src must allow the hosted-field host (tokenfieldUrl). Card fields are cross-origin iframes on that separate host.
Nothing rendersThe container selector must resolve to an element that exists before init(), and the script must have finished loading.
An APM never leaves the page in embedded modeIn autoRedirect: false mode the host must open the provider URL. Handle the pending event and navigate to event.payload.apmPaymentInfo.apmPaymentUrl.
Payment never completes / fields won't submitThe session and paymentToken must be active (respect orderDetails.timeLimit) and the site provisioned for the chosen method. Re-create the session if it expired.
No redirect after paymentCheck autoRedirect is true and the session carries successUrl / cancelUrl / failedUrl. Otherwise navigate yourself in onComplete / onFail.
Apple Pay button never appearsApple Pay only shows in Safari (or other Apple Pay capable browsers) over HTTPS, on a device with a card in Wallet. Also check APPLEPAY is in your site's allowedPaymentOptions.
Apple Pay sheet opens, then closes with a merchant validation errorThe checkout page's hostname is not registered for Apple Pay, or the domain-association file is not reachable. Register that exact hostname (see Apple Pay and Google Pay).
Google Pay button missing or stays disabledCheck your CSP allows https://pay.google.com, GOOGLEPAY is in allowedPaymentOptions, and (if your layout requires it) the terms checkbox is ticked.
Only some methods appearExpected — the SDK shows only the methods enabled in your site's allowedPaymentOptions.
Theme token has no effectCheck the key spelling (tokens are camelCase, e.g. surfaceRaised) and that the value is a valid CSS value. Blank / omitted tokens are never applied.
Pay button hover is still NetValve blueHover is derived from a hex accent. With an rgba() / hsl() / named accent, set accentStrong explicitly.
A method in layout.order never appearsorder only re-orders. The method must also be enabled in your site's allowedPaymentOptions.
Footer still shows after showFooter: falseMake sure layout is passed into the same init() call as the session spread, and that you are not re-initializing elsewhere without it.

Full example​

Redirect mode — the SDK handles encryption, 3DS, APM redirects, and the final navigation:

<div id="nv-checkout"></div>

<script>
// 1. Get a session from YOUR backend (which called /sdk/initializeSession).
fetch("/api/checkout/session", { method: "POST" })
.then((r) => r.json())
.then((session) => {
// 2. Load the SDK from the signed URL in the session.
const script = document.createElement("script");
script.src = session.netvalveScriptSrc;
script.crossOrigin = "anonymous";
script.onload = () => {
// 3. Render the checkout.
window.NetvalveSDK.init({
...session,
container: "#nv-checkout",
autoRedirect: true, // SDK handles success/cancel/failed redirects
});
};
document.head.appendChild(script);
});
</script>