Saving Card Details
Saving Card Details
Save a customer's card for future payments using setup intents. Card details are collected in the browser via the JS SDK — your server never handles raw card data. Once saved, you can charge the card server-side without any customer interaction (see Taking Payments — server-side confirmation).
Flow overview
- Create a customer (server)
- Add a server endpoint that creates a setup intent and returns the
client_secret - On the frontend: get the
client_secret, mount the payment element, and confirm the setup via the JS SDK
1. Create a customer (server)
The Idempotency-Key header lets you safely retry requests if they fail — see Idempotency.
curl -X POST https://api.synaptopay.com/v1/accounts/acct_YOUR_ACCOUNT/customers \
-H "Authorization: Api-Key $API_KEY" \
-H "Idempotency-Key: YOUR_UNIQUE_KEY" \
-H "Content-Type: application/json" \
-d '{
"customer": {
"full_name": "Jane Smith",
"email": "[email protected]",
"phone": "+447700900000"
}
}'{
"name": "accounts/acct_YOUR_ACCOUNT/customers/cus_CUSTOMER_ID",
"full_name": "Jane Smith",
"email": "[email protected]",
"phone": "+447700900000",
"create_time": "2025-10-27T19:09:47Z"
}2. Add a server endpoint to create setup intents (server)
Add an endpoint to your server that creates a setup intent and returns the client_secret to the frontend. The setup intent must be linked to a customer — this is where the saved card will be stored.
Here's the Synapto API call your endpoint needs to make:
curl -X POST https://api.synaptopay.com/v1/accounts/acct_YOUR_ACCOUNT/setup-intents \
-H "Authorization: Api-Key $API_KEY" \
-H "Idempotency-Key: YOUR_UNIQUE_KEY" \
-H "Content-Type: application/json" \
-d '{
"customer": "accounts/acct_YOUR_ACCOUNT/customers/cus_CUSTOMER_ID"
}'{
"name": "accounts/acct_YOUR_ACCOUNT/setup-intents/seti_SETUP_INTENT_ID",
"client_secret": "seti_SETUP_INTENT_ID_secret_SECRET",
"customer": "accounts/acct_YOUR_ACCOUNT/customers/cus_CUSTOMER_ID",
"state": "REQUIRES_PAYMENT_METHOD"
}Your endpoint should return the client_secret from the response to the frontend. In the example below, we assume this endpoint is POST /api/create-setup-intent and returns { "clientSecret": "seti_..._secret_..." }.
3. Collect card details and confirm (frontend)
The frontend side has three steps:
- Get a
client_secret— call your server endpoint from step 2 - Create and mount a payment element — this renders a secure card input form (an iframe) inside an empty element on your page. The customer's raw card data never touches your servers.
- Confirm the setup — when the customer clicks your submit button, call
confirmSetup()to tokenize the card and save it
<!-- Any empty element — the SDK renders the card input form here -->
<div id="card-container"></div>
<!-- Your own submit button — the SDK does not provide one -->
<button id="save-btn">Save Card</button>
<div id="result"></div>
<script src="https://js.synaptopay.com/synapto.js"></script>
<script>
const syn = Synapto("pk_YOUR_PUBLISHABLE_KEY");
// 1. Get a client_secret from your server
fetch("/api/create-setup-intent", { method: "POST" })
.then((res) => res.json())
.then(({ clientSecret }) => {
// 2. Create and mount the payment element
const paymentElement = syn.paymentElement(clientSecret);
paymentElement.mount("#card-container");
// 3. Confirm when the customer clicks save
document.getElementById("save-btn").addEventListener("click", async () => {
const { setupIntent, error } = await paymentElement.confirmSetup();
if (error) {
document.getElementById("result").textContent = "Error: " + error;
} else {
document.getElementById("result").textContent =
"Card saved: " + setupIntent.payment_method;
}
});
});
</script>On success, setupIntent.payment_method contains the saved card's resource name (e.g. accounts/acct_YOUR_ACCOUNT/payment-methods/pm_PAYMENT_METHOD_ID). You can display a confirmation in the browser, but you don't need to send the payment method back to your server — get it from the webhook instead.
4. Get notified of saved card (server)
Listen for the setup_intent.succeeded webhook event to store the saved card on your server. The event payload includes the full setup intent, including the payment_method. See Webhooks for setup instructions.
Store the payment_method against the customer — when you're ready to charge them, pass it in a server-side payment intent (see Taking Payments — server-side confirmation).
Listing saved payment methods
To list the payment methods saved for a customer:
curl -X POST https://api.synaptopay.com/v1/accounts/acct_YOUR_ACCOUNT/payment-methods:list \
-H "Authorization: Api-Key $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"filter": {
"customer": ["accounts/acct_YOUR_ACCOUNT/customers/cus_CUSTOMER_ID"]
}
}'Setup intent states
| State | Description |
|---|---|
REQUIRES_PAYMENT_METHOD | Waiting for card details to be entered |
REQUIRES_CONFIRMATION | Card entered, awaiting confirmation |
PROCESSING | Confirmation in progress |
SUCCEEDED | Card saved successfully |
CANCELED | Setup was canceled |
Updated about 1 month ago