Migrate from iFrame to the Web SDK
A side-by-side API map
This page is a side-by-side API map for merchants moving from the legacy Spreedly iFrame
library to the new Checkout Web SDK (SpreedlyHostedFields /
SpreedlyExpressCheckout).
Conventions used in this doc
- ✅ — direct equivalent
- ⚠️ — equivalent exists but the signature, event name, or payload changed
- 🆕 — new in Checkout Web SDK (no legacy counterpart)
TL;DR — minimum changes to migrate
If your legacy integration only uses init + a few field setters + tokenizeCreditCard,
the migration is small. In order:
- Swap the script tag.
- Replace
Spreedly.init(envKey, { nonce, timestamp, certificateToken, signature, numberEl, cvvEl })
withnew SpreedlyHostedFields({...})+sdk.inAppElements({...})—
see Initialization & lifecycle. - Rename event handlers:
Spreedly.on('paymentMethod', cb)→sdk.on('tokenGenerated', cb)
payload changed (now{ message, tokenResponse: { token, succeeded, payment_method } }).Spreedly.on('errors', cb)→sdk.on('error', cb)payload changed:
legacy always passed an array of error objects; the new SDK's payload varies by
source — astringfor client-side validation errors, Spreedly's error response
body for API failures. See Events.- See Events for the full list.
- Replace
Spreedly.tokenizeCreditCard()withsdk.submit(formData, submitParams)—
see Tokenization (submit). - Move
Spreedly.setParam(...)calls inline:- Cardholder / billing / shipping fields (
first_name,address1,shipping_*,eligible_for_card_updater, …)
→formData(typedHostedFieldsFormData). - Flags (
metadata,allow_blank_name,allow_blank_date,allow_expired_date)
→submitParams.
- Cardholder / billing / shipping fields (
If you also used setRecache / recache, see Recaching.
If you used 3DS, see 3DS — Global / Forter.
Table of Contents
- Script tag
- Initialization & lifecycle
- Field configuration
- Tokenization (submit)
- Recaching
- Events
- 3DS — Global / Forter
- 3DS — Gateway-Specific
- Offsite payments — PayPal & redirect-style
- Offsite payments — Stripe APM
- Offsite payments — Braintree (PayPal/Venmo)
- Express Checkout 🆕
Script tag
| Legacy iFrame | Checkout Web SDK |
|---|---|
<script src="https://core.spreedly.com/iframe/iframe-v1.min.js"> | <script src="https://core.spreedly.com/checkout/sdk/{version}/index.js"> (Hosted Fields) |
<script src="https://core.spreedly.com/iframe/express-3.min.js"> | <script src="https://core.spreedly.com/checkout/elements/{version}/express-checkout.js"> (Express Checkout) |
Reference: web-sdk-sample-app/src/static/shared/utils.js (getSDKScriptUrl)
Initialization & lifecycle
| Legacy iFrame | Checkout Web SDK | Status | Notes |
|---|---|---|---|
Spreedly.init(envKey, { nonce, timestamp, certificateToken, signature, numberEl, cvvEl }) | new SpreedlyHostedFields({ environment_key, nonce, timestamp, certificate_token, signature }) + sdk.inAppElements({ number: { containerId }, cvv: { containerId } }) | ⚠️ | Auth fields are now snake_case and passed to the constructor; iframe mount is a separate explicit call. data-environment-key / data-number-id / data-cvv-id HTML attributes are no longer used. |
(global singleton Spreedly) | (per-instance sdk) | ⚠️ | The new SDK is class-based |
Spreedly.unload() | sdk.destroy() | ⚠️ | Renamed. Removes the iframes, clears on() callbacks, and emits 'close'. Idempotent. After destroy, other SDK methods no-op with a warning. |
Spreedly.reload() | sdk.reload() | ✅ | Same name. Internally tears down current iframes and re-mounts using the same inAppElements() config; merchant on('ready', …) callbacks fire again. |
Spreedly.removeHandlers() | sdk.removeHandlers() | ✅ | Same name; clears all callbacks registered via on(). |
Spreedly.isLoaded() | sdk.isLoaded() | ✅ | Same name; returns true if iframes are mounted and the instance hasn't been destroyed. The 'ready' event is still the recommended entry point. |
Reference: web-sdk-sample-app/src/static/purchase/purchase.js,
web-sdk-sample-app/src/static/tokenize/tokenize.js
Field configuration
All of these are Hosted Fields only in the new SDK; Express Checkout
manages its own UI via sdk.expressCheckout({...}) configuration
(see Express Checkout).
| Legacy iFrame | Checkout Web SDK | Status | Notes |
|---|---|---|---|
Spreedly.setPlaceholder(field, text) | sdk.setPlaceholder('number' | 'cvv', text) | ✅ | |
Spreedly.setStyle(field, css) (CSS string) | sdk.setStyles('number' | 'cvv', { fontSize, color, ... }) (object) | ⚠️ | Renamed (setStyle → setStyles); pass a plain object of camelCase CSS properties instead of a CSS string. |
Spreedly.setStyle('placeholder', css) | sdk.setPlaceholderStyles({ color, fontStyle, ... }) | ⚠️ | Placeholder styling is now its own method (applies to both fields); pass a plain object instead of a CSS string. |
Spreedly.setFieldType(field, type) | sdk.setFieldType('number' | 'cvv', 'text' | 'tel' | 'number' | 'password') | ✅ | |
Spreedly.setLabel(field, value) | sdk.setLabel('number' | 'cvv', value) | ✅ | Sets aria-label on the hosted input. HTML-like tags are stripped (same as legacy). |
Spreedly.setTitle(field, value) | sdk.setTitle('number' | 'cvv', value) | ✅ | Sets the title attribute on the hosted input. |
Spreedly.setInputMode(field, value) | sdk.setInputMode('number' | 'cvv', value) | ✅ | Allowed: 'none' | 'text' | 'numeric' | 'decimal' | 'tel' | 'search' | 'email' | 'url'. |
Spreedly.setRequiredAttribute(field) | sdk.setRequiredAttribute('number' | 'cvv', required = true) | ⚠️ | New SDK accepts a second required boolean (default true) so you can also remove the attribute. |
Spreedly.setNumberFormat('prettyFormat' | 'plainFormat' | 'maskedFormat') | sdk.setNumberFormat(format) | ✅ | |
Spreedly.toggleAutoComplete() | sdk.toggleAutoComplete() | ✅ | |
Spreedly.toggleMask() | sdk.toggleMask() | ✅ | |
Spreedly.transferFocus(field) | sdk.transferFocus('number' | 'cvv' | 'iframe') | ✅ | 'iframe' parks focus on the iframe document (same as legacy). |
Spreedly.validate() | sdk.validate(options?) | ⚠️ | Now async — payload arrives via sdk.on('validation', payload => …). Optional options.allow_blank_name / options.allow_expired_date mirror legacy submit flags. The same validation event fires when submit() is blocked client-side (followed by error). For continuous live state (typing, focus, hover, keys), use sdk.on('fieldStateChange', …). |
Spreedly.resetFields() | sdk.resetFields() | ✅ | Clears both inputs. In recache mode the prefilled disabled number stays — only CVV is cleared. |
| (none — legacy always renders the brand badge) | sdk.setShowCardTypeIcon(false) (Hosted Fields) / uiConfig.showCardTypeIcon: false (Express Checkout) | 🆕 | Hide the built-in card-type badge (e.g. VISA). No legacy equivalent — legacy always shows it. Default is shown. |
Spreedly.setValue('number' | 'cvv', value) | (none — setting card values from the parent page is not supported) | ❌ | Intentionally not migrated. Hosted Fields exists to keep card values in the iframe; setting from the parent page would break PCI scope. |
Spreedly.setParam(name, value) | Pass via sdk.submit(formData, submitParams) | ⚠️ | See Tokenization (submit) — params are passed at submit time, not set ahead. |
Reference: web-sdk-sample-app/src/static/tokenize/tokenize.js
Tokenization (submit)
Hosted Fields. For the Express Checkout flow (single-iframe form), the merchant
doesn't callsubmit()— see Express Checkout — LegacysetParamparity
for how the same legacysetParamfields map ontouiConfig.cardPaymentFormFields+submitParams.
// Legacy
Spreedly.setParam('first_name', 'John');
Spreedly.setParam('last_name', 'Doe');
Spreedly.setParam('month', '12');
Spreedly.setParam('year', '2028');
Spreedly.setParam('email', '[email protected]');
Spreedly.setParam('address1', '123 Main St');
Spreedly.setParam('shipping_city', 'Boston');
Spreedly.setParam('eligible_for_card_updater', true);
Spreedly.setParam('metadata', { order_id: 'ORDER-123' });
Spreedly.setParam('allow_blank_name', true);
Spreedly.tokenizeCreditCard();// Checkout Web SDK — every legacy setParam field has a typed slot
sdk.submit(
{
first_name: 'John',
last_name: 'Doe',
month: '12',
year: '2028',
email: '[email protected]',
address1: '123 Main St',
shipping_city: 'Boston',
eligible_for_card_updater: true,
},
{
metadata: { order_id: 'ORDER-123' },
allow_blank_name: true,
}
);| Legacy iFrame | Checkout Web SDK | Status | |
|---|---|---|---|
Spreedly.tokenizeCreditCard(opts?) — returned false so it could be used directly as an inline onsubmit handler | sdk.submit(formData, submitParams?) — returns void; call event.preventDefault() yourself in form submit handlers | ⚠️ | |
Spreedly.setParam('first_name' | 'last_name' | 'full_name' | 'month' | 'year' | 'email' | 'address1' | ... | 'shipping_*', val) | formData (typed HostedFieldsFormData; mandatory: first_name, last_name, month, year) | ✅ | Every legacy permittedStringParams field has a typed slot on formData — see the typed HostedFieldsFormData surface below. Unknown keys are dropped server-side and the SDK logs a console warning listing the offending keys so typos (e.g. address_1 vs address1) surface fast. |
Spreedly.setParam('metadata', {...}) | submitParams.metadata | ✅ | |
Spreedly.setParam('allow_blank_name' | 'allow_blank_date' | 'allow_expired_date', true) | submitParams.allow_blank_name / submitParams.allow_blank_date / submitParams.allow_expired_date | ✅ | |
Spreedly.setParam('eligible_for_card_updater', true) | formData.eligible_for_card_updater (boolean) | ✅ | Legacy boolean flag; lives on formData because it ends up on payment_method.credit_card server-side, alongside billing/shipping. |
Token via 'paymentMethod' event | Token via 'tokenGenerated' event — payload is { message, tokenResponse: { token, succeeded, payment_method: { token, card_type, last_four_digits, ... } } } | ✅ | Payload shape changed; see Events. |
Reference: web-sdk-sample-app/src/static/tokenize/tokenize.js,
checkout-web-sdk/docs/tokenization/hosted-fields/INTEGRATION_GUIDE.md
Typed formData surface
formData surfacesdk.submit(formData, submitParams) accepts the typed HostedFieldsFormData interface
exported from @spreedly/core/types. It mirrors the legacy Spreedly.setParam(...) allow-list
one-to-one:
type HostedFieldsFormData = {
// Mandatory (matches legacy)
first_name: string;
last_name: string;
month: string; // 'MM'
year: string; // 'YYYY'
// Cardholder
full_name?: string;
email?: string;
company?: string;
phone_number?: string;
// Billing address
address1?: string;
address2?: string;
city?: string;
state?: string;
zip?: string;
country?: string;
// Shipping address (every legacy `shipping_*` field)
shipping_address1?: string;
shipping_address2?: string;
shipping_city?: string;
shipping_state?: string;
shipping_zip?: string;
shipping_country?: string;
shipping_phone_number?: string;
// Legacy boolean flag (was `permittedBooleanParams` in the iframe)
eligible_for_card_updater?: boolean;
};Card number and CVV are NEVER passed here — they live exclusively in the hosted iframes
for PCI scope.
Pass any unknown key (e.g. address_1 instead of address1) and the SDK logs a single
console.warn listing the offending keys plus the full whitelist, so typos are easy to
spot in development.
Recaching
// Legacy
Spreedly.setRecache('RETAINED-PM-TOKEN', { last_four_digits: '4242', card_type: 'visa' });
Spreedly.on('recacheReady', () => { /* prompt for CVV */ });
Spreedly.recache();
Spreedly.on('recache', (token, pm) => { /* success */ });// Checkout Web SDK (Hosted Fields)
sdk.setRecache('RETAINED-PM-TOKEN', {
card_type: 'visa',
last_four_digits: '4242',
storage_state: 'retained',
month: '12',
year: '2028',
});
sdk.on('recacheReady', () => { /* prompt for CVV */ });
sdk.recache();
sdk.on('recacheSuccess', (response) => { /* response.payment_method... */ });| Legacy iFrame | Checkout Web SDK | Status | Notes |
|---|---|---|---|
Spreedly.setRecache(token, { last_four_digits?, card_type? }) | sdk.setRecache(token, RecacheOptions) | ✅ | New SDK requires card_type, last_four_digits, storage_state: 'retained', month, year. |
Spreedly.recache() | sdk.recache() (Hosted Fields) / Form auto-submit (Express Checkout) | ✅ | Express Checkout handles recache submission via its own submit button — no recache() call needed. |
Spreedly.on('recacheReady', cb) | sdk.on('recacheReady', cb) | ✅ | |
Spreedly.on('recache', (token, pm) => …) | sdk.on('recacheSuccess', (response) => …) | ✅ | Event renamed; payload is the recache response object. |
Reference: web-sdk-sample-app/src/static/recache/recache.js,
checkout-web-sdk/docs/recaching/INTEGRATION_GUIDE.md
Events
All events are subscribed via sdk.on(eventName, callback), same shape as legacy. The
event name and the callback argument shape changed for several events — those rows
are marked ⚠️.
| Legacy iFrame event | Checkout Web SDK event | Status | Notes |
|---|---|---|---|
'ready' | 'ready' | ✅ | |
'paymentMethod' (token, pm) | 'tokenGenerated' (payload) | ⚠️ | Renamed and payload changed. Payload is { message, tokenResponse: { token, succeeded, payment_method: { token, card_type, last_four_digits, ... } } }. |
'errors' (errorsArray) | 'error' (payload) | ⚠️ | Renamed (singular) and payload changed — it varies by source: a string for client-side validation and guard errors (e.g. 'Invalid card number', 'Please wait before submitting again'); Spreedly's error response body (object with an errors array) for API failures; { message, attribute? } objects for recache configuration errors. Handle both strings and objects. |
'validation' (payload) | 'validation' (payload) | ✅ | Fired in response to sdk.validate() and again when submit() is blocked client-side. Payload includes cardType, validNumber, validCvv, cvvLength, numberLength, luhnValid, iin?, maskedNumber?, allow_blank_name?, allow_expired_date?. |
'fieldEvent' (name, type, ...) | 'fieldStateChange' (payload) | ⚠️ | Renamed; single object payload. Includes the same numeric snapshot as validation plus field, action (focus | blur | input | mouseover | mouseout | enter | escape | tab | shiftTab), focused, hovered?. Opt in to PAN-prefix iin via sdk.setFieldStateReporting({ includeIin: true }). |
'consoleError' (error) | 'consoleError' (payload) | ⚠️ | Same name; payload shape is now { msg, url, line, col, error, field: 'number' | 'cvv' }. Fired when an uncaught error occurs inside one of the hosted iframes. |
'numberSet' / 'cvvSet' / 'sourceSet' | (none) | ❌ | Mirror legacy setValue / source flows that aren't supported (intentionally — see Field configuration). |
'recacheReady' | 'recacheReady' | ✅ | |
'recache' (token, pm) | 'recacheSuccess' (response) | ⚠️ | Renamed; payload is the recache response object { message, token, payment_method }. |
| (none) | 'cvvExpired' (subset of 'error') | 🆕 | New SDK clears CVV after PCI DSS 3.2.3 TTL (3 minutes) and emits an error with { message: 'CVV expired after 3 minutes', reason: 'PCI DSS 3.2.3 TTL compliance' }. |
'3ds:status' (event) (single dispatcher; switch on event.action) | Typed callbacks on the SpreedlyThreeDSLifecycle constructor | ⚠️ | See 3DS — replaced by callbacks: { onChallenge, onSuccess, onError, onDeviceFingerprint?, onTriggerCompletion? }. |
| none | 'close' (Hosted Fields after destroy(), and Express Checkout) | 🆕 | |
| none | 'offsiteTokenGenerated' / 'offsitePaymentError' | 🆕 | See Offsite payments. |
3DS — Global / Forter
// Legacy
Spreedly.on('3ds:status', (event) => {
switch (event.action) {
case 'challenge': /* show modal */ break;
case 'succeeded': /* success */ break;
case 'error': /* failure */ break;
}
});
const lifecycle = new Spreedly.ThreeDS.Lifecycle({
environmentKey,
hiddenIframeLocation: 'device-fingerprint',
challengeIframeLocation: 'challenge',
transactionToken,
});
lifecycle.start();// Checkout Web SDK
const lifecycle = new SpreedlyThreeDSLifecycle({
transactionToken,
hiddenIframeLocation: 'device-fingerprint',
challengeIframeLocation: 'challenge-container',
environmentKey,
callbacks: {
onChallenge: (e) => { /* show modal */ },
onSuccess: (e) => { /* success */ },
onError: (e) => { /* failure */ },
},
});
lifecycle.start();| Legacy iFrame | Checkout Web SDK | Status | Notes |
|---|---|---|---|
new Spreedly.ThreeDS.Lifecycle({ environmentKey, hiddenIframeLocation, challengeIframeLocation, transactionToken, challengeIframeClasses? }) | new SpreedlyThreeDSLifecycle({ transactionToken, hiddenIframeLocation, challengeIframeLocation, environmentKey, callbacks, challengeIframeClasses? }) | ✅ | Constructor moved to a top-level class (no Spreedly.ThreeDS namespace). |
Spreedly.on('3ds:status', handler) (single dispatcher with event.action) | callbacks: { onChallenge, onSuccess, onError, onDeviceFingerprint?, onTriggerCompletion? } (typed callbacks) | ✅ | Replaced by named callbacks on the constructor. |
lifecycle.start() | lifecycle.start() | ✅ | |
Spreedly.ThreeDS.serialize(challengeWindowSize, acceptHeader) | serializeBrowserInfo(challengeWindowSize, acceptHeader) (global) | ✅ | Renamed; same signature. |
| (none) | lifecycle.stop() | 🆕 | Cancel/cleanup helper. |
Reference: web-sdk-sample-app/src/static/purchase-with-3ds/purchase-with-3ds.js,
checkout-web-sdk/docs/three-ds/global/INTEGRATION_GUIDE.md
3DS — Gateway-Specific
| Legacy iFrame | Checkout Web SDK | Status | Notes |
|---|---|---|---|
new Spreedly.ThreeDS.Lifecycle({ ... }) (same call; backend uses attempt_3dsecure: true + three_ds_version: '2' instead of sca_provider_key) | new SpreedlyThreeDSLifecycle({ ..., callbacks: { onDeviceFingerprint, onChallenge, onSuccess, onError, onTriggerCompletion } }) | ✅ | Same lifecycle class; gateway-specific flow is driven by the backend payload (no sca_provider_key) and uses the additional onDeviceFingerprint / onTriggerCompletion callbacks not fired in Forter mode. |
Reference: web-sdk-sample-app/src/static/purchase-with-3ds-gateway-specific/purchase-with-3ds-gateway-specific.js,
checkout-web-sdk/docs/three-ds/gateway-specific/INTEGRATION_GUIDE.md
Offsite payments — PayPal & redirect-style
The legacy approach was a transparent-redirect HTML form posting to
https://core.spreedly.com/v1/payment_methods directly. The new SDK exposes
a programmatic API that calls the same endpoint without a page navigation.
<!-- Legacy: hand-built form -->
<form action="https://core.spreedly.com/v1/payment_methods" method="POST">
<input name="environment_key" value="..." />
<input name="payment_method_type" value="paypal" />
<input name="redirect_url" value="https://merchant/handle-redirect" />
...
</form>// Checkout Web SDK — API flow (recommended)
sdk.on('offsiteTokenGenerated', ({ token, paymentMethodType }) => {
// POST token to your backend → run the gateway purchase
});
sdk.on('offsitePaymentError', (err) => { /* ... */ });
sdk.setupOffsitePayment({
paymentMethodType: 'paypal', // or 'pix', 'boleto_bancario', 'oxxo', 'nupay', ...
email: '[email protected]',
fullName: 'Ana Santos',
// ... optional billing/contact fields
});
sdk.submitOffsitePayment();| Legacy iFrame / Spreedly form | Checkout Web SDK | Status |
|---|---|---|
Hand-built <form action="…/v1/payment_methods" method="POST"> | sdk.setupOffsitePayment(config) + sdk.submitOffsitePayment() | ✅ |
| Transparent-redirect (browser navigates to Spreedly) | API flow (no navigation) — emits 'offsiteTokenGenerated' with token | ✅ |
Form-based redirect with redirect_url | Pass redirectUrl in setupOffsitePayment config (form submission still supported as a legacy fallback) | ✅ |
| none | sdk.clearOffsitePayment() | 🆕 |
Reference: web-sdk-sample-app/src/static/offsite-payments/offsite-payments.js,
checkout-web-sdk/docs/offsite-payments/general/INTEGRATION_GUIDE.md
Offsite payments — Stripe APM
// Legacy
const element = Spreedly.createStripePaymentElement({
publishableKey,
clientSecret,
transactionToken,
paymentElement: '#payment-element',
appearance,
});
element.confirmPayment();// Checkout Web SDK
const stripeApm = new SpreedlyStripeAPM({
publishableKey,
clientSecret,
transactionToken,
paymentElement: 'stripe-payment-element', // element ID, not selector
appearance,
});
stripeApm.mount();
await stripeApm.confirmPayment();| Legacy iFrame | Checkout Web SDK | Status | Notes |
|---|---|---|---|
Spreedly.createStripePaymentElement(opts) | new SpreedlyStripeAPM(opts) | ✅ | OO API. |
| (implicit mount inside the call above) | stripeApm.mount() | ✅ | Mount is now an explicit step. |
element.confirmPayment() | stripeApm.confirmPayment() | ✅ | Now async; returns { error? }. |
paymentElement: '#selector' | paymentElement: 'element-id' | ⚠️ | Pass the element ID without #. |
Reference: web-sdk-sample-app/src/static/offsite-payments/stripe-apm/stripe-apm.js,
checkout-web-sdk/docs/offsite-payments/stripe-apm/INTEGRATION_GUIDE.md
Offsite payments — Braintree (PayPal/Venmo)
// Legacy
Spreedly.createBraintreePaymentElements({
callbackFunction: handlePaymentResult,
transactionToken,
paymentElements: { paypal: 'paypal-button', venmo: 'venmo-button' },
environmentKey,
});// Checkout Web SDK
const braintree = new SpreedlyBraintree({
transactionToken,
environmentKey,
paymentElements: { paypal: 'paypal-button', venmo: 'venmo-button' },
onPaymentResult: handlePaymentResult,
onButtonAction: handleButtonAction, // optional
style: { paypal: { color: 'gold', shape: 'rect', height: 45 } }, // optional
});
const result = await braintree.mount();| Legacy iFrame | Checkout Web SDK | Status | Notes |
|---|---|---|---|
Spreedly.createBraintreePaymentElements({ callbackFunction, transactionToken, paymentElements, environmentKey }) | new SpreedlyBraintree({ transactionToken, environmentKey, paymentElements, onPaymentResult, onButtonAction?, style? }) | ✅ | OO API; callbackFunction → onPaymentResult. |
| (implicit mount) | await braintree.mount() | ✅ | Returns { paypalRendered?, venmoRendered?, error? }. |
| (no styling hooks) | style: { paypal: { color, shape, height, layout } } | 🆕 | |
| (no button-action callback) | onButtonAction({ state: 'Initiated' | 'Clicked', data, actions }) | 🆕 |
Reference: web-sdk-sample-app/src/static/offsite-payments/braintree/braintree.js,
checkout-web-sdk/docs/offsite-payments/braintree/INTEGRATION_GUIDE.md
Express Checkout 🆕
Pre-built single-iframe checkout form. No equivalent in the legacy iFrame SDK
(legacy express-3.min.js was the same Hosted-Fields-style two-iframe API,
just bundled differently).
const sdk = new SpreedlyExpressCheckout({
environment_key, certificate_token, nonce, signature, timestamp,
});
sdk.on('ready', () => {});
sdk.on('tokenGenerated', (resp) => {});
sdk.on('error', (err) => {});
sdk.on('close', () => {});
const checkout = sdk.expressCheckout({
parentContainerId: 'checkout-container', // omit for full-screen dialog mode
});
sdk.updateTextElement('title', 'Complete Your Purchase');
sdk.updateTextElement('submitBtnText', 'Pay $99.00');
sdk.addField('phone_number', { /* ... */ });
sdk.removeField('company');
sdk.setFieldConfig('first_name', { /* ... */ });
sdk.close(true);Legacy setParam parity
setParam parityIn legacy, Spreedly.setParam('first_name' | 'address1' | 'shipping_*' | …, val) set
field values into a parent-page Hosted-Fields-style form. Express Checkout doesn't
work that way — the iframe IS the entire form, so the merchant doesn't supply field
values; they configure which fields the iframe should render. The shopper fills them
in, and they're submitted with the tokenization request.
Map legacy setParam to Express Checkout like this:
Legacy setParam(name, value) | Express Checkout equivalent | Status |
|---|---|---|
'first_name' / 'last_name' / 'month' / 'year' (mandatory) | Rendered by default in uiConfig.cardPaymentFormFields | ✅ |
'full_name' / 'company' / 'email' / 'phone_number' | Add to uiConfig.cardPaymentFormFields (typed via AdditionalCardPaymentFormFields) | ✅ |
'address1' / 'address2' / 'city' / 'state' / 'zip' / 'country' | Add to uiConfig.cardPaymentFormFields | ✅ |
All 'shipping_*' variants | Add to uiConfig.cardPaymentFormFields | ✅ |
'metadata' (object) | submitParams.metadata | ✅ |
'allow_blank_name' / 'allow_blank_date' / 'allow_expired_date' (boolean) | submitParams.allow_blank_name / …blank_date / …expired_date | ✅ |
'eligible_for_card_updater' (boolean) | submitParams.eligible_for_card_updater | ✅ |
Example — render an email input and tokenize as eligible for the Card Updater:
sdk.expressCheckout({
parentContainerId: 'checkout-container',
uiConfig: {
cardPaymentFormFields: {
// Default mandatory fields are merged in automatically; just add the extras.
email: { fieldName: 'email', label: 'Email', isRequired: true, size: 12, isMasked: false, placeholder: '[email protected]', styles: {} },
address1: { fieldName: 'address1', label: 'Address 1', isRequired: false, size: 12, isMasked: false, placeholder: '123 Main St', styles: {} },
},
},
submitParams: {
metadata: { order_id: 'ORDER-123' },
eligible_for_card_updater: true,
},
});API surface
| API | Status |
|---|---|
new SpreedlyExpressCheckout(authDetails) | 🆕 |
sdk.expressCheckout({ parentContainerId?, uiConfig?, submitParams?, id?, className? }) — embedded when parentContainerId is given, full-screen dialog otherwise; returns { destroy } | 🆕 |
sdk.updateTextElement(key, value) | 🆕 |
sdk.addField(name, config) / sdk.removeField(name) / sdk.setFieldConfig(name, config) | 🆕 |
sdk.close(force?) | 🆕 |
Event: 'close' | 🆕 |
Reference: web-sdk-sample-app/src/static/tokenize/tokenize.js?sdk=express-checkout,
checkout-web-sdk/docs/tokenization/express-checkout/INTEGRATION_GUIDE.md
Updated about 3 hours ago

