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.
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:
- Your server calls
POST /sdk/initializeSessionwith your API credentials and gets back a session (apaymentToken, ajwtToken, the SDK script URL, and your site's payment-page layout). - Your server returns that session to the browser.
- The browser loads the SDK script from
session.netvalveScriptSrc. NetvalveSDK.init(session)renders the checkout — only the payment methods your site enables.- The customer pays. The SDK encrypts the card fields, calls
/sdk/sale, runs any 3DS challenge, and polls APM status for you. - On a terminal result the SDK either redirects to your success / cancel / failed URLs, or calls your
onComplete/onFailcallbacks — 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 NetValve payment-API domain (
{{paymentApiUrl}}from onboarding) — where your server posts the session-creation call. The session response then carries anendpointsblock that self-describes every host the SDK talks to, so you never hardcode environment hostnames in your page. - Your payment methods (cards, PIX, PSE, and APMs — 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 three NetValve hosts named in the session's
endpointsblock — the SDK bundle, the hosted card-field host, and the payment-API host (see Security & CSP below).
Contact the NetValve team to ensure your site is provisioned and you have credentials for API authentication.
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 API Key and Client ID in the netvalve-api-key and netvalve-client-id headers (see API Authentication) — 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 — to that same domain, authenticating with the session's jwtToken as a Bearer token. You never handle that token yourself.
For an APM-first checkout (e.g. starting directly on PIX or PSE), also send paymentOption (e.g. apm_pix) and alternativePaymentMethod (the customer's document data: userType, documentType, documentNumber, socialName, fiscalCountry) in this request.
The response includes everything the SDK needs: netvalveScriptSrc (the script URL), version and integrity (the SDK bundle's Subresource-Integrity hash), paymentToken, jwtToken, the endpoints block (apiBaseUrl, tokenfieldUrl, scriptSrc — the hosts for this environment), and initConfig (your site layout, order details, and redirect URLs).
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 — it is signed with the version and tokens — 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
| Option | Type | Required | Description |
|---|---|---|---|
container | string | HTMLElement | Yes | CSS selector or DOM node the SDK renders into. Must exist before init(). |
autoRedirect | boolean | No (default true) | When true, the SDK navigates the browser to successUrl / cancelUrl / failedUrl on a terminal result. Set false to handle navigation yourself in callbacks. |
onComplete | function(SdkEvent) | No* | Called once when the payment is approved. |
onFail | function(SdkEvent) | No* | Called once when the payment is declined or errors. |
onEvent | function(SdkEvent) | No | Called for every event (ready, pending, complete, fail, cancel). Required in embedded mode to drive APM redirects (see Step 4). |
...session | object | Yes | The spread initializeSession response — supplies paymentToken, jwtToken, netvalveScriptSrc, the endpoints block, 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
| Field | Type | Description |
|---|---|---|
type | string | "ready" | "pending" | "complete" | "fail" | "cancel" |
method | string | null | Which method produced it: "card" | "pix" | "pse" | "volt" | "paypal" | "venmo" | "spei" | "bitpace" | "sezzle" | "system" |
payload | object | The transaction result (see below). Empty for ready. |
at | string | ISO-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
| Field | Meaning |
|---|---|
transactionID | NetValve transaction id. Appended to successUrl / failedUrl as ?transactionID= in redirect mode. |
responseCodeType | APPROVED | PENDING | DECLINED | HARD_DECLINE | ERROR |
orderState | PAID | PENDING | AWAIT_3DS | DECLINED | EXPIRED | CANCELED |
responseMessage | Human-readable status to surface in your UI. |
apmPaymentInfo.apmPaymentUrl | On 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.
| Method | Site option (allowedPaymentOptions) | What the customer sees |
|---|---|---|
| Cards (Visa / Mastercard / Amex / …) | VISA, MASTERCARD, AMEX, DISCOVER, DINERS, JCB | Hosted, PCI-safe card fields. 3-D Secure runs automatically inside the SDK when the issuer requires it. |
| PIX | PIX | A QR code; the SDK polls until the bank confirms payment, then completes. |
| PSE | PSE | Customer picks their bank, is redirected to it, and back to your URLs. |
| Volt (open banking) | VOLT | Customer selects country, then bank, then is redirected to authorise and back. |
| PayPal | PAYPAL | PayPal's hosted button (via Braintree); tokenises and completes without leaving the page. |
| Venmo | VENMO | Native Venmo button (via Braintree); tokenises and completes without leaving the page. |
| SPEI | SPEI | Bank-transfer instructions (CLABE / reference); the SDK polls until the transfer clears. |
| Bitpace | BITPACE | Redirect to the Bitpace crypto-payment page, then back to your URLs. |
| Sezzle | SEZZLE | Redirect 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).
Apple Pay and Google Pay are implemented in the SDK but not yet generally available. They require additional per-merchant platform setup (Apple merchant-id + domain verification; Google gateway parameters) that is not enabled yet. Contact the NetValve team if you need wallet support — they are omitted here until GA.
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/initializeSessioncall uses them (yournetvalve-api-keyandnetvalve-client-id). The browser only ever sees the session — a short-livedpaymentToken+jwtToken; the SDK uses thatjwtTokenas 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
endpointsblock names the three hosts to allow: the SDK bundle host (scriptSrcorigin), the hosted card-field host (tokenfieldUrl— the card iframes, a separate origin from the API), 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
Replace YOUR-ENV with the hosts from the session's endpoints block (they differ per environment).
Troubleshooting
| Symptom | Likely cause / fix |
|---|---|
SDK script fails to load / window.NetvalveSDK undefined | Use the exact netvalveScriptSrc from the session (it is signed). Check script-src in your CSP and that you waited for script.onload. |
| Checkout renders but card fields are blank | Your CSP frame-src must allow the hosted-field host (tokenfieldUrl). Card fields are cross-origin iframes on that separate host. |
| Nothing renders | The 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 mode | In 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 submit | The 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 payment | Check autoRedirect is true and the session carries successUrl / cancelUrl / failedUrl. Otherwise navigate yourself in onComplete / onFail. |
| Only some methods appear | Expected — the SDK shows only the methods enabled in your site's allowedPaymentOptions. |
Full example
<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>