JavaScript SDK
JavaScript SDK
The Synapto JS SDK securely collects card details in the browser. It renders card inputs inside an iframe so raw card data never touches your servers.
For complete integration walkthroughs, see Taking Payments and Saving Cards.
Installation
Add the script tag to your page. Use the URL matching your environment:
| Environment | Script URL |
|---|---|
| Sandbox | https://js.synaptopay-sandbox.com/synapto.js |
| Production | https://js.synaptopay.com/synapto.js |
<script src="https://js.synaptopay.com/synapto.js"></script>Initialization
const syn = Synapto("pk_YOUR_PUBLISHABLE_KEY");The constructor accepts an optional second argument for configuration:
const syn = Synapto("pk_YOUR_PUBLISHABLE_KEY", { theme: "dark" });Find your publishable key in the Dashboard under Settings > Developer. See Authentication for details.
Theming
The SDK supports theming to match your site's look and feel. Pass a theme when initializing the SDK — it applies to all elements (payment element, card tokenization, and 3D Secure modals).
Built-in presets
Use "light" (default) or "dark":
const syn = Synapto("pk_YOUR_PUBLISHABLE_KEY", { theme: "dark" });Custom colors
Pass an object with any combination of these properties to customize individual colors:
| Property | Description | Light default | Dark default |
|---|---|---|---|
background | Page and container background | #FFFFFF | #141A2C |
foreground | Labels and text | #0C1761 | #F8FAFC |
buttonBackground | Submit button background | #0190F3 | #42A6F0 |
buttonForeground | Submit button text | #FFFFFF | #0C1761 |
inputBackground | Input field background | #F9F9FA | #1A1E30 |
inputForeground | Input field text | #0C1761 | #F8FAFC |
inputForegroundInvalid | Validation error text | #e7000b | #FF6467 |
inputPlaceholder | Input placeholder text | #A3A8B1 | #6D7696 |
inputBorder | Input border | #E2E2E2 | #232A48 |
inputBorderInvalid | Input border on validation error | #E2E2E2 | rgba(251, 44, 54, 0.5) |
accent | Focus rings and highlights | #0191F5 | #42A6F0 |
All properties are optional — omitted values fall back to the light theme defaults.
const syn = Synapto("pk_YOUR_PUBLISHABLE_KEY", {
theme: {
background: "#1a1a2e",
foreground: "#eaeaea",
buttonBackground: "#16c784",
buttonForeground: "#ffffff",
inputBackground: "#262641",
inputForeground: "#eaeaea",
inputBorder: "#3a3f5c",
accent: "#16c784",
},
});Google Pay
The Google Pay button can be rendered with either a black or white background.
The SDK picks one from the theme you pass:
theme | Google Pay button |
|---|---|
"dark" | White |
"light" | Black |
| A custom colors object | Black |
| Omitted | Black |
The default value can be overwritten with the walletButtonTheme.googlePay option, which accepts either "black" or "white".
const syn = Synapto("pk_YOUR_PUBLISHABLE_KEY", {
theme: { background: "#101828", foreground: "#F8FAFC" },
walletButtonTheme: {
googlePay: "white", // "black" | "white"
},
});How it works
- Your server creates a payment intent or setup intent via the API, receiving a
client_secret - Your server passes the
client_secretto the frontend - The frontend creates a payment element with the
client_secretand mounts it to a DOM element — this renders a card input form in a secure iframe - When the customer submits, the frontend calls
confirmPayment()orconfirmSetup()— the SDK tokenizes the card data and sends it to Synapto - The SDK returns the result (success or error) to your frontend
The client_secret authorizes the customer to view and confirm the specific intent. Your API key is never exposed to the browser.
Payment element
syn.paymentElement(clientSecret, options?)
syn.paymentElement(clientSecret, options?)Creates a payment element bound to a payment intent or setup intent.
const paymentElement = syn.paymentElement("pi_..._secret_...");The optional second argument configures the fields the element collects:
| Option | Type | Description |
|---|---|---|
fields.billingDetails | "auto" | "never" | object | "never" suppresses every billing field. Pass an object to target individual ones. |
fields.billingDetails.name | "auto" | "never" | "auto" (default) collects the cardholder name in the element. "never" hides the input — you supply the name instead. |
defaultValues.billingDetails.name | string | undefined | Pre-fills the cardholder name. On its own the input stays visible and editable. |
If you already collect the cardholder name as part of your own billing details, pass it through and hide the input so the customer doesn't type it twice:
const paymentElement = syn.paymentElement("pi_..._secret_...", {
fields: { billingDetails: { name: "never" } },
defaultValues: { billingDetails: { name: "Ada Lovelace" } },
});If you don't know the name until checkout completes, supply it at confirmation instead:
const paymentElement = syn.paymentElement("pi_..._secret_...", {
fields: { billingDetails: { name: "never" } },
});
await paymentElement.confirmPayment({
paymentMethodData: { billingDetails: { name: "Ada Lovelace" } },
});A name given at confirmation wins over defaultValues. The name is sent as part of the card's billing details either way.
If you suppress the input and then supply no name by either route, the element re-displays the input at confirmation and asks the customer for it, rather than taking a payment with no cardholder name.
name is currently the only billing detail these options cover — the element doesn't collect email, phone or address.
paymentElement.mount(selector)
paymentElement.mount(selector)Renders the card input form inside the specified DOM element.
paymentElement.mount("#payment-container");paymentElement.confirmPayment(options?)
paymentElement.confirmPayment(options?)Confirms a payment intent — tokenizes the card data, sends it to Synapto, and processes the payment. Returns a promise.
const { paymentIntent, error } = await paymentElement.confirmPayment();Returns:
| Field | Type | Description |
|---|---|---|
paymentIntent.name | string | Resource name |
paymentIntent.state | string | REQUIRES_PAYMENT_METHOD, REQUIRES_CONFIRMATION, PROCESSING, SUCCEEDED, or CANCELED |
paymentIntent.amount | string | Amount in smallest currency unit |
paymentIntent.currency | string | Three-letter ISO currency code |
paymentIntent.customer | string | Customer resource name (if set) |
paymentIntent.latest_charge | string | Most recent charge resource name |
error | string | undefined | Error message if payment failed |
paymentElement.confirmSetup(options?)
paymentElement.confirmSetup(options?)Confirms a setup intent — tokenizes the card data and saves it as a payment method. Returns a promise.
const { setupIntent, error } = await paymentElement.confirmSetup();Returns:
| Field | Type | Description |
|---|---|---|
setupIntent.name | string | Resource name |
setupIntent.state | string | REQUIRES_PAYMENT_METHOD, REQUIRES_CONFIRMATION, PROCESSING, SUCCEEDED, or CANCELED |
setupIntent.customer | string | Customer resource name |
setupIntent.payment_method | string | Saved payment method resource name |
error | string | undefined | Error message if setup failed |
paymentElement.awaitReady()
paymentElement.awaitReady()Waits until the payment element iframe is loaded and ready. Call this if you need to ensure the element is initialized before confirming.
await paymentElement.awaitReady();3D Secure
Both confirmPayment() and confirmSetup() handle 3D Secure automatically. If the card issuer requires authentication, the SDK displays a challenge modal and resolves the promise once the customer completes it.
You can customize the 3D Secure behavior with an options object:
const { paymentIntent, error } = await paymentElement.confirmPayment({
modalSelector: "#my-3ds-modal",
onModal: (visible) => {
console.log("3DS modal visible:", visible);
},
});| Option | Type | Description |
|---|---|---|
modalSelector | string | undefined | CSS selector for a custom 3DS modal container. If not provided, the SDK creates one automatically. |
onModal | function | undefined | Callback invoked with true when the 3DS challenge is shown and false when it completes. |
paymentMethodData.billingDetails.name | string | undefined | Cardholder name, for elements configured with fields.billingDetails.name: "never". |
Updated 29 days ago