Snap JavaScript SDK (v2) — Quick Start Guide
Public edition • v2 • StableOverview
Snap’s JavaScript SDK lets you add a “Pay with Snap” option to your website. When a shopper clicks the button, a secure window opens for the application and checkout flow. When finished, the window closes and your site receives the result (for example, an applicationId on approval).
How it works
- Your server requests a short-lived access token from Snap and caches it (valid ~24 hours).
- Your webpage loads the Snap SDK v2 and initializes it with the token.
- On button click, you call
actions.launchCheckout(transaction). Snap returns results via callbacks.
Step 1 — Verify requirements
- Snap Developer credentials: Client ID and Client Secret.
- A server that can make HTTPS requests and keep secrets (Node, Python, Java, and so on).
- Frontend where you will render the Snap mark and checkout button.
- Serve over http(s) (for example,
http://localhost:5500). Avoidfile://URLs.
Step 2 — Choose environment
Sandbox (testing)
audience: https://api-release.snapfinance.com/platform/v1Use Sandbox while building and testing.
Production (live)
audience: https://api.snapfinance.com/platform/v1Switch to Production when you are live.
Step 3 — Get an access token
Obtain a token and cache it on your server. The token is valid for 24 hours.
Important
Do not call Auth0 directly. Use the Snap OAuth endpoints below to request the bearer token used by the SDK.
Production token endpoint
https://auth.snapfinance.com/oauth/tokenSandbox token endpoint
https://auth-sandbox.snapfinance.com/oauth/token3.1 Token request fields
client_idClient ID provided by Snap.
client_secretClient Secret provided by Snap.
audienceSandbox:
Production:
https://api-release.snapfinance.com/platform/v1Production:
https://api.snapfinance.com/platform/v1grant_typeAlways
client_credentials.3.2 Token request (cURL)
curl --location 'https://auth-sandbox.snapfinance.com/oauth/token' \
--header 'Content-Type: application/json' \
--data '{
"client_id": "YOUR_CLIENT_ID",
"client_secret": "YOUR_CLIENT_SECRET",
"audience": "https://api-release.snapfinance.com/platform/v1",
"grant_type": "client_credentials"
}'
3.3 Token response
{
"access_token": "eyJhbGciOi...REDACTED",
"scope": "array of scopes",
"expires_in": 86400,
"token_type": "Bearer"
}
Step 4 — Add the Web SDK (v2)
4.1 Include the correct script
<!-- Sandbox (testing) -->
<script src="https://js.snapfinance.com/sandbox/v2/snap-sdk.js"></script>
<!-- Production (live) -->
<!-- <script src="https://js.snapfinance.com/v2/snap-sdk.js"></script> -->
4.2 Initialize with a server-fetched token
<script>
// const { token } = await fetch('/api/snap/token').then(r => r.json());
snap.init("YOUR_BEARER_TOKEN");
</script>
Step 5 — Build the transaction object
Money fields must be strings with two decimals and quantity must be an integer. Use a unique orderId each checkout.
<script>
// Example cart
const items = [
{ price: 100.00, itemId: "PROD-001", description: "Sample item 1", sku: "SKU-001", quantity: 1, leasable: true },
{ price: 50.00, itemId: "PROD-002", description: "Sample item 2", sku: "SKU-002", quantity: 1, leasable: true }
];
const taxAmount = 8.25, shippingAmount = 12.00, discountAmount = 5.00;
function toMoney(v){ return Number(v).toFixed(2); }
function computeSubTotal(arr){ return arr.reduce((s,i)=> s + Number(i.price)*Number(i.quantity), 0); }
function buildTransaction(){
const sub = computeSubTotal(items);
const total = sub + taxAmount + shippingAmount - discountAmount;
return {
customerInformation: {
email:"buyer@example.com", firstName:"Jane", lastName:"Doe",
billingAddress:{ streetAddress:"123 Main St", city:"Salt Lake City", state:"UT", country:"US", postalCode:"84101", unit:"" }
},
cartInformation: {
currencyCode:"USD",
taxAmount: toMoney(taxAmount),
shippingAmount: toMoney(shippingAmount),
discountAmount: toMoney(discountAmount),
totalAmount: toMoney(total),
orderId: "ORD-" + Date.now(),
items: items.map(i => ({
price: toMoney(i.price), itemId: i.itemId, description: i.description, sku: i.sku,
quantity: Number(i.quantity), leasable: Boolean(i.leasable)
})),
shippingAddress:{ streetAddress:"123 Main St", city:"Salt Lake City", state:"UT", country:"US", postalCode:"84101", unit:"" }
}
};
}
</script>
Step 6 — Render mark and button
<div id="snap-checkout-mark"></div>
<div id="snap-checkout-button"></div>
<input type="text" id="applicationId" placeholder="Application ID will appear here" />
<script>
const markMount = document.getElementById('snap-checkout-mark');
const btnMount = document.getElementById('snap-checkout-button');
function ensureMark(){
if (markMount.dataset.mounted === 'true' || markMount.childElementCount) return;
snap.checkoutMark({ style:{ color:'dark', height:'40' } }).render('snap-checkout-mark');
markMount.dataset.mounted = 'true';
}
function ensureButton(){
if (btnMount.dataset.mounted === 'true' || btnMount.querySelector('iframe')) return;
snap.checkoutButton({
style:{ color:'dark', shape:'pill', height:'42' },
onClick:(d,a)=>a.launchCheckout(buildTransaction()),
onApproved:(d)=>{ const el=document.getElementById('applicationId'); if(d?.applicationId&&el) el.value=d.applicationId; }
}).render('snap-checkout-button');
btnMount.dataset.mounted = 'true';
}
ensureMark(); ensureButton();
</script>
Step 7 — Validate totals
<script>
function sumItems(arr){ return arr.reduce((s,i)=> s + Number(i.price)*Number(i.quantity), 0); }
function validateTransaction(tx){
const ci = tx?.cartInformation; if (!ci) throw new Error('cartInformation missing');
if (!ci.orderId) throw new Error('orderId is required');
const computed = sumItems(ci.items) + Number(ci.taxAmount) + Number(ci.shippingAmount) - Number(ci.discountAmount);
if (Math.abs(computed - Number(ci.totalAmount)) > 0.01) throw new Error('totalAmount mismatch');
}
</script>
Step 8 — Troubleshoot
| Symptom | Cause | Fix |
|---|---|---|
| Money fields rejected | Numbers sent for money fields | Send strings with two decimals |
| Quantity rejected | Quantity sent as string | Send integer |
| “System Error” | Schema mismatch or unsupported field | Remove unsupported fields and verify totals |
| “Session not initialized” | Render before snap.init() | Initialize once, then render |
Step 9 — Security best practices
- Keep
client_secreton the server only. - Use HTTPS for all requests.
- Cache the token for approximately 24 hours; refresh slightly before expiry.
- Validate and sanitize all inputs from the browser.
Step 10 — Go‑live checklist
- Server endpoint to request and cache a token.
- Include the correct SDK v2 script for your environment.
- Initialize once with a valid token:
snap.init(token). - Build a valid
transaction(string money, integer quantity). - Render mark and button; call
actions.launchCheckout(transaction)on click. - Handle callbacks and persist
applicationIdwith yourorderId.
Reference — Full example
<script src="https://js.snapfinance.com/sandbox/v2/snap-sdk.js"></script>
<script>
snap.init("YOUR_BEARER_TOKEN");
/* buildTransaction() from above */
snap.checkoutMark({ style:{ color:"dark", height:"40" }}).render('snap-checkout-mark');
snap.checkoutButton({
style:{ color:"dark", shape:"pill", height:"42" },
onClick:(d,a)=>a.launchCheckout(buildTransaction())
}).render('snap-checkout-button');
</script>